From 0bc1db1631b356af279f72014bf84e0e851af138 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 13 Dec 2025 14:32:37 +0000 Subject: [PATCH] movedTo or copiedTo --- daemon_post_profile.py | 29 +++++++++++++++++------------ daemon_utils.py | 4 ++++ desktop_client.py | 3 +++ inbox_receive.py | 11 +++++++++-- migrate.py | 8 ++++++-- person.py | 15 ++++++++++----- posts.py | 2 +- relationships.py | 11 ++++++++--- webapp_profile.py | 35 +++++++++++++++++++++++++---------- 9 files changed, 83 insertions(+), 35 deletions(-) diff --git a/daemon_post_profile.py b/daemon_post_profile.py index 0fb558b3b..15787b00a 100644 --- a/daemon_post_profile.py +++ b/daemon_post_profile.py @@ -1748,18 +1748,23 @@ def _profile_post_moved(actor_json: {}, fields: {}, send_move_activity: bool) -> bool: """ HTTP POST account moved to new address """ - moved_to = '' - if actor_json.get('movedTo'): - moved_to = actor_json['movedTo'] - if fields.get('movedTo'): - if fields['movedTo'] != moved_to and resembles_url(fields['movedTo']): - actor_json['movedTo'] = fields['movedTo'] - send_move_activity = True - actor_changed = True - else: - if moved_to: - del actor_json['movedTo'] - actor_changed = True + fieldnames = ('movedTo', 'copiedTo') + for fieldname in fieldnames: + moved_to = '' + if actor_json.get(fieldname): + moved_to = actor_json[fieldname] + + if fields.get(fieldname): + if fields[fieldname] != moved_to and \ + resembles_url(fields[fieldname]): + actor_json[fieldname] = fields[fieldname] + send_move_activity = True + actor_changed = True + else: + if moved_to: + del actor_json[fieldname] + actor_changed = True + return actor_changed, send_move_activity diff --git a/daemon_utils.py b/daemon_utils.py index 9ffc6e51b..098df9881 100644 --- a/daemon_utils.py +++ b/daemon_utils.py @@ -674,6 +674,10 @@ def show_person_options(self, calling_domain: str, path: str, moved_to = actor_json['movedTo'] if '"' in moved_to: moved_to = moved_to.split('"')[1] + elif actor_json.get('copiedTo'): + moved_to = actor_json['copiedTo'] + if '"' in moved_to: + moved_to = moved_to.split('"')[1] if actor_json.get('type'): if actor_json['type'] == 'Group': is_group = True diff --git a/desktop_client.py b/desktop_client.py index bacb97ef7..6379dc147 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -1004,6 +1004,9 @@ def _desktop_show_actor(http_prefix: str, if actor_json.get('movedTo'): say_str = 'Moved to ' + html.unescape(actor_json['movedTo']) _say_command(say_str, say_str, screenreader, system_language, espeak) + elif actor_json.get('copiedTo'): + say_str = 'Copied to ' + html.unescape(actor_json['copiedTo']) + _say_command(say_str, say_str, screenreader, system_language, espeak) if actor_json.get('alsoKnownAs'): also_known_as_str = '' ctr = 0 diff --git a/inbox_receive.py b/inbox_receive.py index 1609c1271..7fe97904f 100644 --- a/inbox_receive.py +++ b/inbox_receive.py @@ -248,17 +248,24 @@ def _person_receive_update(base_dir: str, if debug: print('actor updated for ' + idx) + person_has_moved_url = None if person_json.get('movedTo'): + person_has_moved_url = person_json['movedTo'] + elif person_json.get('copiedTo'): + person_has_moved_url = person_json['copiedTo'] + + if person_has_moved_url: prev_domain_full = None prev_domain, prev_port = get_domain_from_actor(idx) if prev_domain: prev_domain_full = get_full_domain(prev_domain, prev_port) prev_nickname = get_nickname_from_actor(idx) new_domain = None - new_domain, new_port = get_domain_from_actor(person_json['movedTo']) + new_domain, new_port = get_domain_from_actor(person_has_moved_url) + new_domain_full = None if new_domain: new_domain_full = get_full_domain(new_domain, new_port) - new_nickname = get_nickname_from_actor(person_json['movedTo']) + new_nickname = get_nickname_from_actor(person_has_moved_url) if prev_nickname and prev_domain_full and new_domain and \ new_nickname and new_domain_full: diff --git a/migrate.py b/migrate.py index f6c614149..fb87b2b75 100644 --- a/migrate.py +++ b/migrate.py @@ -111,9 +111,13 @@ def _update_moved_handle(base_dir: str, nickname: str, domain: str, signing_priv_key_pem, None, mitm_servers) if not person_json: return ctr - if not person_json.get('movedTo'): + if not person_json.get('movedTo') and \ + not person_json.get('copiedTo'): return ctr - moved_to_url = person_json['movedTo'] + if person_json.get('movedTo'): + moved_to_url = person_json['movedTo'] + else: + moved_to_url = person_json['copiedTo'] if '://' not in moved_to_url: return ctr if '.' not in moved_to_url: diff --git a/person.py b/person.py index bdd78e0f2..86ade6f30 100644 --- a/person.py +++ b/person.py @@ -356,12 +356,17 @@ def get_actor_move_json(actor_json: {}) -> {}: within the actor https://codeberg.org/fediverse/fep/src/branch/main/fep/7628/fep-7628.md """ - if not actor_json.get('movedTo'): + if not actor_json.get('movedTo') and \ + not actor_json.get('copiedTo'): return None - if '://' not in actor_json['movedTo'] or \ - '.' not in actor_json['movedTo']: + if actor_json.get('movedTo'): + moved_url = actor_json['movedTo'] + else: + moved_url = actor_json['copiedTo'] + if '://' not in moved_url or \ + '.' not in moved_url: return None - if actor_json['movedTo'] == actor_json['id']: + if moved_url == actor_json['id']: return None pub_number, _ = get_status_number() return { @@ -373,7 +378,7 @@ def get_actor_move_json(actor_json: {}) -> {}: "type": "Move", "actor": actor_json['id'], "object": actor_json['id'], - "target": actor_json['movedTo'], + "target": moved_url, "to": ['https://www.w3.org/ns/activitystreams#Public'], "cc": [actor_json['id'] + '/followers'] } diff --git a/posts.py b/posts.py index 07f5a98db..7eaee3a4e 100644 --- a/posts.py +++ b/posts.py @@ -439,7 +439,7 @@ def get_person_box(signing_priv_key_pem: str, origin_domain: str, possible_display_name, 'en'): display_name = '*FILTERED*' # have they moved? - if person_json.get('movedTo'): + if person_json.get('movedTo') or person_json.get('copiedTo'): display_name += ' ⌂' store_person_in_cache(base_dir, person_url, person_json, diff --git a/relationships.py b/relationships.py index a0fdaae39..9c5b44e22 100644 --- a/relationships.py +++ b/relationships.py @@ -278,11 +278,16 @@ def update_moved_actors(base_dir: str, debug: bool) -> None: if not actor_json: continue if not actor_json.get('movedTo'): - continue - nickname = get_nickname_from_actor(actor_json['movedTo']) + if not actor_json.get('copiedTo'): + continue + if actor_json.get('movedTo'): + moved_url = actor_json['movedTo'] + else: + moved_url = actor_json['copiedTo'] + nickname = get_nickname_from_actor(moved_url) if not nickname: continue - domain, port = get_domain_from_actor(actor_json['movedTo']) + domain, port = get_domain_from_actor(moved_url) if not domain: continue domain_full = get_full_domain(domain, port) diff --git a/webapp_profile.py b/webapp_profile.py index 9b860bdc6..f2c68c1bb 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -350,12 +350,18 @@ def html_profile_after_search(authorized: bool, blog_url = get_blog_address(profile_json) moved_to = '' - if profile_json.get('movedTo'): - moved_to = profile_json['movedTo'] - if '"' in moved_to: - moved_to = moved_to.split('"')[1] - moved_to = remove_html(moved_to) - display_name += ' ⌂' + if profile_json.get('movedTo') or profile_json.get('copiedTo'): + if profile_json.get('movedTo'): + moved_to = profile_json['movedTo'] + else: + moved_to = profile_json['copiedTo'] + if isinstance(moved_to, str): + if '"' in moved_to: + moved_to = moved_to.split('"')[1] + moved_to = remove_html(moved_to) + display_name += ' ⌂' + else: + moved_to = '' you_follow = \ is_following_actor(base_dir, @@ -765,6 +771,7 @@ def _get_profile_header(base_dir: str, http_prefix: str, nickname: str, '

' + joined_str + ' ' + \ joined_date.split('T')[0] + '
\n' if moved_to: + moved_to = remove_html(moved_to) new_nickname = get_nickname_from_actor(moved_to) new_domain, new_port = get_domain_from_actor(moved_to) if new_nickname and new_domain: @@ -1484,10 +1491,16 @@ def html_profile(signing_priv_key_pem: str, avatar_description = replace_strings(avatar_description, replacements) moved_to = '' - if profile_json.get('movedTo'): - moved_to = profile_json['movedTo'] - if '"' in moved_to: - moved_to = moved_to.split('"')[1] + if profile_json.get('movedTo') or profile_json.get('copiedTo'): + if profile_json.get('movedTo'): + moved_to = profile_json['movedTo'] + else: + moved_to = profile_json['copiedTo'] + if isinstance(moved_to, str): + if '"' in moved_to: + moved_to = moved_to.split('"')[1] + else: + moved_to = '' also_known_as = None if profile_json.get('alsoKnownAs'): @@ -3469,6 +3482,8 @@ def html_edit_profile(server, translate: {}, if actor_json: if actor_json.get('movedTo'): moved_to = actor_json['movedTo'] + elif actor_json.get('copiedTo'): + moved_to = actor_json['copiedTo'] featured_hashtags = get_featured_hashtags(actor_json) donate_url = get_donation_url(actor_json) website_url = get_website(actor_json, translate)