conversation can also be called thread

See https://codeberg.org/fediverse/fep/src/branch/main/fep/76ea/fep-76ea.md
merge-requests/30/head
Bob Mottram 2024-10-06 10:41:21 +01:00
parent f2bd491900
commit 2933af9a05
9 changed files with 76 additions and 14 deletions

View File

@ -1236,9 +1236,14 @@ def mute_post(base_dir: str, nickname: str, domain: str, port: int,
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
actor = local_actor_url(http_prefix, nickname, domain_full) actor = local_actor_url(http_prefix, nickname, domain_full)
# Due to lack of AP specification maintenance, a conversation can also be
# referred to as a thread or (confusingly) "context"
if post_json_obj.get('conversation'): if post_json_obj.get('conversation'):
mute_conversation(base_dir, nickname, domain, mute_conversation(base_dir, nickname, domain,
post_json_obj['conversation']) post_json_obj['conversation'])
elif post_json_obj.get('thread'):
mute_conversation(base_dir, nickname, domain,
post_json_obj['thread'])
elif post_json_obj.get('context'): elif post_json_obj.get('context'):
mute_conversation(base_dir, nickname, domain, mute_conversation(base_dir, nickname, domain,
post_json_obj['context']) post_json_obj['context'])
@ -1380,9 +1385,14 @@ def unmute_post(base_dir: str, nickname: str, domain: str, port: int,
if has_object_string(post_json_object, debug): if has_object_string(post_json_object, debug):
also_update_post_id = remove_id_ending(post_json_object['object']) also_update_post_id = remove_id_ending(post_json_object['object'])
# Due to lack of AP specification maintenance, a conversation can also be
# referred to as a thread or (confusingly) "context"
if post_json_obj.get('conversation'): if post_json_obj.get('conversation'):
unmute_conversation(base_dir, nickname, domain, unmute_conversation(base_dir, nickname, domain,
post_json_obj['conversation']) post_json_obj['conversation'])
elif post_json_obj.get('thread'):
unmute_conversation(base_dir, nickname, domain,
post_json_obj['thread'])
elif post_json_obj.get('context'): elif post_json_obj.get('context'):
unmute_conversation(base_dir, nickname, domain, unmute_conversation(base_dir, nickname, domain,
post_json_obj['context']) post_json_obj['context'])

View File

@ -26,10 +26,13 @@ from session import get_json_valid
def _get_conversation_filename(base_dir: str, nickname: str, domain: str, def _get_conversation_filename(base_dir: str, nickname: str, domain: str,
post_json_object: {}) -> str: post_json_object: {}) -> str:
"""Returns the conversation filename """Returns the conversation filename
Due to lack of AP specification maintenance, a conversation can also be
referred to as a thread or (confusingly) "context"
""" """
if not has_object_dict(post_json_object): if not has_object_dict(post_json_object):
return None return None
if not post_json_object['object'].get('conversation') and \ if not post_json_object['object'].get('conversation') and \
not post_json_object['object'].get('thread') and \
not post_json_object['object'].get('context'): not post_json_object['object'].get('context'):
return None return None
if not post_json_object['object'].get('id'): if not post_json_object['object'].get('id'):
@ -39,8 +42,12 @@ def _get_conversation_filename(base_dir: str, nickname: str, domain: str,
os.mkdir(conversation_dir) os.mkdir(conversation_dir)
if post_json_object['object'].get('conversation'): if post_json_object['object'].get('conversation'):
conversation_id = post_json_object['object']['conversation'] conversation_id = post_json_object['object']['conversation']
elif post_json_object['object'].get('thread'):
conversation_id = post_json_object['object']['thread']
else: else:
conversation_id = post_json_object['object']['context'] conversation_id = post_json_object['object']['context']
if not isinstance(conversation_id, str):
return None
conversation_id = conversation_id.replace('/', '#') conversation_id = conversation_id.replace('/', '#')
return conversation_dir + '/' + conversation_id return conversation_dir + '/' + conversation_id
@ -80,6 +87,9 @@ def mute_conversation(base_dir: str, nickname: str, domain: str,
conversation_id: str) -> None: conversation_id: str) -> None:
"""Mutes the given conversation """Mutes the given conversation
""" """
if not isinstance(conversation_id, str):
return
conversation_dir = acct_dir(base_dir, nickname, domain) + '/conversation' conversation_dir = acct_dir(base_dir, nickname, domain) + '/conversation'
conversation_filename = \ conversation_filename = \
conversation_dir + '/' + conversation_id.replace('/', '#') conversation_dir + '/' + conversation_id.replace('/', '#')
@ -99,6 +109,9 @@ def unmute_conversation(base_dir: str, nickname: str, domain: str,
conversation_id: str) -> None: conversation_id: str) -> None:
"""Unmutes the given conversation """Unmutes the given conversation
""" """
if not isinstance(conversation_id, str):
return
conversation_dir = acct_dir(base_dir, nickname, domain) + '/conversation' conversation_dir = acct_dir(base_dir, nickname, domain) + '/conversation'
conversation_filename = \ conversation_filename = \
conversation_dir + '/' + conversation_id.replace('/', '#') conversation_dir + '/' + conversation_id.replace('/', '#')

View File

@ -1964,9 +1964,15 @@ def run_desktop_client(base_dir: str, proxy_type: str, http_prefix: str,
if post_json_object['object'].get('summary'): if post_json_object['object'].get('summary'):
subject = post_json_object['object']['summary'] subject = post_json_object['object']['summary']
conversation_id = None conversation_id = None
# Due to lack of AP specification maintenance,
# a conversation can also be referred to as a
# thread or (confusingly) "context"
if post_json_object['object'].get('conversation'): if post_json_object['object'].get('conversation'):
conversation_id = \ conversation_id = \
post_json_object['object']['conversation'] post_json_object['object']['conversation']
elif post_json_object['object'].get('thread'):
conversation_id = \
post_json_object['object']['thread']
elif post_json_object['object'].get('context'): elif post_json_object['object'].get('context'):
conversation_id = \ conversation_id = \
post_json_object['object']['context'] post_json_object['object']['context']

View File

@ -213,9 +213,10 @@ def _command_options() -> None:
parser.add_argument('-n', '--nickname', dest='nickname', type=str, parser.add_argument('-n', '--nickname', dest='nickname', type=str,
default=None, default=None,
help='Nickname of the account to use') help='Nickname of the account to use')
parser.add_argument('--conversation', dest='conversation', type=str, parser.add_argument('--conversation', '--thread', dest='conversation',
default=None, type=str, default=None,
help='Download a conversation for the given post id') help='Download a conversation/thread ' +
'for the given post id')
parser.add_argument('--screenreader', dest='screenreader', type=str, parser.add_argument('--screenreader', dest='screenreader', type=str,
default=None, default=None,
help='Name of the screen reader: ' + help='Name of the screen reader: ' +

View File

@ -1532,9 +1532,13 @@ def _create_reply_notification_file(base_dir: str, nickname: str, domain: str,
# replies index will be updated # replies index will be updated
update_index_list.append('tlreplies') update_index_list.append('tlreplies')
# Due to lack of AP specification maintenance, a conversation can also be
# referred to as a thread or (confusingly) "context"
conversation_id = None conversation_id = None
if post_json_object['object'].get('conversation'): if post_json_object['object'].get('conversation'):
conversation_id = post_json_object['object']['conversation'] conversation_id = post_json_object['object']['conversation']
elif post_json_object['object'].get('thread'):
conversation_id = post_json_object['object']['thread']
elif post_json_object['object'].get('context'): elif post_json_object['object'].get('context'):
conversation_id = post_json_object['object']['context'] conversation_id = post_json_object['object']['context']

View File

@ -1281,6 +1281,8 @@ def _create_post_s2s(base_dir: str, nickname: str, domain: str, port: int,
local_actor_url(http_prefix, nickname, domain) local_actor_url(http_prefix, nickname, domain)
if not conversation_id: if not conversation_id:
conversation_id = new_post_id conversation_id = new_post_id
if not isinstance(conversation_id, str):
conversation_id = new_post_id
# add opt-outs as in: # add opt-outs as in:
# https://codeberg.org/fediverse/fep/src/branch/main/fep/5e53/fep-5e53.md # https://codeberg.org/fediverse/fep/src/branch/main/fep/5e53/fep-5e53.md
new_post = { new_post = {
@ -1388,6 +1390,8 @@ def _create_post_c2s(base_dir: str, nickname: str, domain: str, port: int,
http_prefix + '://' + domain + '/@' + nickname + '/' + status_number http_prefix + '://' + domain + '/@' + nickname + '/' + status_number
if not conversation_id: if not conversation_id:
conversation_id = new_post_id conversation_id = new_post_id
if not isinstance(conversation_id, str):
conversation_id = new_post_id
# add opt-outs as in: # add opt-outs as in:
# https://codeberg.org/fediverse/fep/src/branch/main/fep/5e53/fep-5e53.md # https://codeberg.org/fediverse/fep/src/branch/main/fep/5e53/fep-5e53.md
new_post = { new_post = {
@ -5160,7 +5164,8 @@ def _novel_fields_for_person(nickname: str, domain: str,
'secGPC', 'secGPC',
'xRobotsTag', 'xRobotsTag',
'content_is_html', 'content_is_html',
'repliesCount' 'repliesCount',
'thread'
) )
for post_filename in posts_in_box: for post_filename in posts_in_box:
post_filename = post_filename.name post_filename = post_filename.name
@ -6377,6 +6382,8 @@ def is_muted_conv(base_dir: str, nickname: str, domain: str, post_id: str,
"""Returns true if the given post is muted """Returns true if the given post is muted
""" """
if conversation_id: if conversation_id:
if not isinstance(conversation_id, str):
return False
conv_muted_filename = \ conv_muted_filename = \
acct_dir(base_dir, nickname, domain) + '/conversation/' + \ acct_dir(base_dir, nickname, domain) + '/conversation/' + \
conversation_id.replace('/', '#') + '.muted' conversation_id.replace('/', '#') + '.muted'

View File

@ -2481,7 +2481,10 @@ def _delete_conversation_post(base_dir: str, nickname: str, domain: str,
""" """
if not has_object_dict(post_json_object): if not has_object_dict(post_json_object):
return False return False
# Due to lack of AP specification maintenance, a conversation can also be
# referred to as a thread or (confusingly) "context"
if not post_json_object['object'].get('conversation') and \ if not post_json_object['object'].get('conversation') and \
not post_json_object['object'].get('thread') and \
not post_json_object['object'].get('context'): not post_json_object['object'].get('context'):
return False return False
if not post_json_object['object'].get('id'): if not post_json_object['object'].get('id'):
@ -2490,8 +2493,12 @@ def _delete_conversation_post(base_dir: str, nickname: str, domain: str,
acct_dir(base_dir, nickname, domain) + '/conversation' acct_dir(base_dir, nickname, domain) + '/conversation'
if post_json_object['object'].get('conversation'): if post_json_object['object'].get('conversation'):
conversation_id = post_json_object['object']['conversation'] conversation_id = post_json_object['object']['conversation']
elif post_json_object['object'].get('thread'):
conversation_id = post_json_object['object']['thread']
else: else:
conversation_id = post_json_object['object']['context'] conversation_id = post_json_object['object']['context']
if not isinstance(conversation_id, str):
return False
conversation_id = conversation_id.replace('/', '#') conversation_id = conversation_id.replace('/', '#')
post_id = post_json_object['object']['id'] post_id = post_json_object['object']['id']
conversation_filename = conversation_dir + '/' + conversation_id conversation_filename = conversation_dir + '/' + conversation_id
@ -2760,7 +2767,7 @@ def _get_reserved_words() -> str:
'bookmark', 'bookmarks', 'tlbookmarks', 'bookmark', 'bookmarks', 'tlbookmarks',
'ignores', 'linksmobile', 'newswiremobile', 'ignores', 'linksmobile', 'newswiremobile',
'minimal', 'search', 'eventdelete', 'minimal', 'search', 'eventdelete',
'searchemoji', 'catalog', 'conversationId', 'searchemoji', 'catalog', 'conversationId', 'thread',
'mention', 'http', 'https', 'ipfs', 'ipns', 'mention', 'http', 'https', 'ipfs', 'ipns',
'ontologies', 'data', 'postedit', 'moved', 'ontologies', 'data', 'postedit', 'moved',
'inactive', 'activitypub', 'actors', 'inactive', 'activitypub', 'actors',

View File

@ -295,10 +295,16 @@ def html_new_post(edit_post_params: {},
for _, buy_url in buy_links.items(): for _, buy_url in buy_links.items():
default_buy_site = buy_url default_buy_site = buy_url
break break
# Due to lack of AP specification maintenance, a conversation can also
# be referred to as a thread or (confusingly) "context"
if edited_post_json['object'].get('conversation'): if edited_post_json['object'].get('conversation'):
conversation_id = edited_post_json['object']['conversation'] conversation_id = edited_post_json['object']['conversation']
elif edited_post_json['object'].get('thread'):
conversation_id = edited_post_json['object']['thread']
elif edited_post_json['object'].get('context'): elif edited_post_json['object'].get('context'):
conversation_id = edited_post_json['object']['context'] conversation_id = edited_post_json['object']['context']
if edit_post_params.get('replyTo'): if edit_post_params.get('replyTo'):
in_reply_to = edit_post_params['replyTo'] in_reply_to = edit_post_params['replyTo']
if edit_post_params['scope'] == 'dm': if edit_post_params['scope'] == 'dm':
@ -1113,6 +1119,7 @@ def html_new_post(edit_post_params: {},
dropdown_dm_suffix += '?mention=' + mentioned_actor dropdown_dm_suffix += '?mention=' + mentioned_actor
dropdown_report_suffix += '?mention=' + mentioned_actor dropdown_report_suffix += '?mention=' + mentioned_actor
if conversation_id and in_reply_to: if conversation_id and in_reply_to:
if isinstance(conversation_id, str):
dropdown_new_post_suffix += '?conversationId=' + conversation_id dropdown_new_post_suffix += '?conversationId=' + conversation_id
dropdown_new_blog_suffix += '?conversationId=' + conversation_id dropdown_new_blog_suffix += '?conversationId=' + conversation_id
dropdown_unlisted_suffix += '?conversationId=' + conversation_id dropdown_unlisted_suffix += '?conversationId=' + conversation_id
@ -1159,6 +1166,7 @@ def html_new_post(edit_post_params: {},
new_post_form += \ new_post_form += \
' <input type="hidden" name="replychatmsg" value="yes">\n' ' <input type="hidden" name="replychatmsg" value="yes">\n'
if conversation_id: if conversation_id:
if isinstance(conversation_id, str):
new_post_form += \ new_post_form += \
' <input type="hidden" name="conversationId" value="' + \ ' <input type="hidden" name="conversationId" value="' + \
conversation_id + '">\n' conversation_id + '">\n'

View File

@ -653,6 +653,7 @@ def _get_reply_icon_html(base_dir: str, nickname: str, domain: str,
reply_to_this_post_str = translate[reply_to_this_post_str] reply_to_this_post_str = translate[reply_to_this_post_str]
conversation_str = '' conversation_str = ''
if conversation_id: if conversation_id:
if isinstance(conversation_id, str):
conversation_str = '?conversationId=' + conversation_id conversation_str = '?conversationId=' + conversation_id
if is_public_reply: if is_public_reply:
actor_url = get_actor_from_post(post_json_object) actor_url = get_actor_from_post(post_json_object)
@ -2500,9 +2501,14 @@ def individual_post_as_html(signing_priv_key_pem: str,
conversation_id = None conversation_id = None
if isinstance(post_json_object['object'], dict): if isinstance(post_json_object['object'], dict):
# Due to lack of AP specification maintenance, a conversation can also
# be referred to as a thread or (confusingly) "context"
if 'conversation' in post_json_object['object']: if 'conversation' in post_json_object['object']:
if post_json_object['object']['conversation']: if post_json_object['object']['conversation']:
conversation_id = post_json_object['object']['conversation'] conversation_id = post_json_object['object']['conversation']
elif 'thread' in post_json_object['object']:
if post_json_object['object']['thread']:
conversation_id = post_json_object['object']['thread']
elif 'context' in post_json_object['object']: elif 'context' in post_json_object['object']:
if post_json_object['object']['context']: if post_json_object['object']['context']:
conversation_id = post_json_object['object']['context'] conversation_id = post_json_object['object']['context']