Enable reading friendica-style actors

main
Bob Mottram 2024-01-09 16:59:23 +00:00
parent 0035c0a8c7
commit e0ea772681
25 changed files with 300 additions and 191 deletions

View File

@ -22,6 +22,7 @@ from utils import has_group_type
from utils import local_actor_url from utils import local_actor_url
from utils import has_actor from utils import has_actor
from utils import has_object_string_type from utils import has_object_string_type
from utils import get_actor_from_post
def _create_accept_reject(base_dir: str, federation_list: [], def _create_accept_reject(base_dir: str, federation_list: [],
@ -37,7 +38,8 @@ def _create_accept_reject(base_dir: str, federation_list: [],
if not object_json.get('actor'): if not object_json.get('actor'):
return None return None
if not url_permitted(object_json['actor'], federation_list): actor_url = get_actor_from_post(object_json)
if not url_permitted(actor_url, federation_list):
return None return None
domain = get_full_domain(domain, port) domain = get_full_domain(domain, port)
@ -101,7 +103,7 @@ def _accept_follow(base_dir: str, message_json: {},
return return
if debug: if debug:
print('DEBUG: follow Accept received ' + str(message_json)) print('DEBUG: follow Accept received ' + str(message_json))
this_actor = message_json['object']['actor'] this_actor = get_actor_from_post(message_json['object'])
nickname = get_nickname_from_actor(this_actor) nickname = get_nickname_from_actor(this_actor)
if not nickname: if not nickname:
print('WARN: no nickname found in ' + this_actor) print('WARN: no nickname found in ' + this_actor)
@ -205,17 +207,18 @@ def receive_accept_reject(base_dir: str, domain: str, message_json: {},
return False return False
if not has_actor(message_json, debug): if not has_actor(message_json, debug):
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + '. Assuming single user instance.') message_json['type'] + '. Assuming single user instance.')
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(actor_url)
if not domain_permitted(domain, federation_list): if not domain_permitted(domain, federation_list):
if debug: if debug:
print('DEBUG: ' + message_json['type'] + print('DEBUG: ' + message_json['type'] +
' from domain not permitted - ' + domain) ' from domain not permitted - ' + domain)
return False return False
nickname = get_nickname_from_actor(message_json['actor']) nickname = get_nickname_from_actor(actor_url)
if not nickname: if not nickname:
# single user instance # single user instance
nickname = 'dev' nickname = 'dev'

View File

@ -27,6 +27,7 @@ from utils import local_actor_url
from utils import replace_users_with_at from utils import replace_users_with_at
from utils import has_actor from utils import has_actor
from utils import has_object_string_type from utils import has_object_string_type
from utils import get_actor_from_post
from posts import send_signed_json from posts import send_signed_json
from posts import get_person_box from posts import get_person_box
from session import post_json from session import post_json
@ -61,11 +62,12 @@ def is_self_announce(post_json_object: {}) -> bool:
return False return False
if not post_json_object.get('object'): if not post_json_object.get('object'):
return False return False
if not isinstance(post_json_object['actor'], str): actor_url = get_actor_from_post(post_json_object)
if not isinstance(actor_url, str):
return False return False
if not isinstance(post_json_object['object'], str): if not isinstance(post_json_object['object'], str):
return False return False
return post_json_object['actor'] in post_json_object['object'] return actor_url in post_json_object['object']
def outbox_announce(recent_posts_cache: {}, def outbox_announce(recent_posts_cache: {},
@ -86,20 +88,21 @@ def outbox_announce(recent_posts_cache: {},
return False return False
if is_self_announce(message_json): if is_self_announce(message_json):
return False return False
nickname = get_nickname_from_actor(message_json['actor']) actor_url = get_actor_from_post(message_json)
nickname = get_nickname_from_actor(actor_url)
if not nickname: if not nickname:
print('WARN: no nickname found in ' + message_json['actor']) print('WARN: no nickname found in ' + actor_url)
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(actor_url)
if not domain: if not domain:
print('WARN: no domain found in ' + message_json['actor']) print('WARN: no domain found in ' + actor_url)
return False return False
post_filename = locate_post(base_dir, nickname, domain, post_filename = locate_post(base_dir, nickname, domain,
message_json['object']) message_json['object'])
if post_filename: if post_filename:
update_announce_collection(recent_posts_cache, update_announce_collection(recent_posts_cache,
base_dir, post_filename, base_dir, post_filename,
message_json['actor'], actor_url,
nickname, domain, debug) nickname, domain, debug)
return True return True
elif message_json['type'] == 'Undo': elif message_json['type'] == 'Undo':
@ -108,20 +111,21 @@ def outbox_announce(recent_posts_cache: {},
if message_json['object']['type'] == 'Announce': if message_json['object']['type'] == 'Announce':
if not isinstance(message_json['object']['object'], str): if not isinstance(message_json['object']['object'], str):
return False return False
nickname = get_nickname_from_actor(message_json['actor']) actor_url = get_actor_from_post(message_json)
nickname = get_nickname_from_actor(actor_url)
if not nickname: if not nickname:
print('WARN: no nickname found in ' + message_json['actor']) print('WARN: no nickname found in ' + actor_url)
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(actor_url)
if not domain: if not domain:
print('WARN: no domain found in ' + message_json['actor']) print('WARN: no domain found in ' + actor_url)
return False return False
post_filename = locate_post(base_dir, nickname, domain, post_filename = locate_post(base_dir, nickname, domain,
message_json['object']['object']) message_json['object']['object'])
if post_filename: if post_filename:
undo_announce_collection_entry(recent_posts_cache, undo_announce_collection_entry(recent_posts_cache,
base_dir, post_filename, base_dir, post_filename,
message_json['actor'], actor_url,
domain, debug) domain, debug)
return True return True
return False return False
@ -458,7 +462,8 @@ def outbox_undo_announce(recent_posts_cache: {},
print('DEBUG: c2s undo announce post not found in inbox or outbox') print('DEBUG: c2s undo announce post not found in inbox or outbox')
print(message_id) print(message_id)
return True return True
actor_url = get_actor_from_post(message_json)
undo_announce_collection_entry(recent_posts_cache, base_dir, post_filename, undo_announce_collection_entry(recent_posts_cache, base_dir, post_filename,
message_json['actor'], domain, debug) actor_url, domain, debug)
if debug: if debug:
print('DEBUG: post undo announce via c2s - ' + post_filename) print('DEBUG: post undo announce via c2s - ' + post_filename)

View File

@ -21,6 +21,7 @@ from utils import save_json
from utils import acct_dir from utils import acct_dir
from utils import local_actor_url from utils import local_actor_url
from utils import has_actor from utils import has_actor
from utils import get_actor_from_post
def set_availability(base_dir: str, nickname: str, domain: str, def set_availability(base_dir: str, nickname: str, domain: str,
@ -67,12 +68,13 @@ def outbox_availability(base_dir: str, nickname: str, message_json: {},
if not has_object_string(message_json, debug): if not has_object_string(message_json, debug):
return False return False
actor_nickname = get_nickname_from_actor(message_json['actor']) actor_url = get_actor_from_post(message_json)
actor_nickname = get_nickname_from_actor(actor_url)
if not actor_nickname: if not actor_nickname:
return False return False
if actor_nickname != nickname: if actor_nickname != nickname:
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(actor_url)
if not domain: if not domain:
return False return False
status = message_json['object'].replace('"', '') status = message_json['object'].replace('"', '')

View File

@ -37,6 +37,7 @@ from utils import acct_dir
from utils import local_actor_url from utils import local_actor_url
from utils import has_actor from utils import has_actor
from utils import text_in_file from utils import text_in_file
from utils import get_actor_from_post
from conversation import mute_conversation from conversation import mute_conversation
from conversation import unmute_conversation from conversation import unmute_conversation
from auth import create_basic_auth_header from auth import create_basic_auth_header
@ -1364,7 +1365,8 @@ def outbox_mute(base_dir: str, http_prefix: str,
if not has_actor(message_json, debug): if not has_actor(message_json, debug):
return return
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
if not message_json['actor'].endswith(domain_full + '/users/' + nickname): actor_url = get_actor_from_post(message_json)
if not actor_url.endswith(domain_full + '/users/' + nickname):
return return
if not message_json['type'] == 'Ignore': if not message_json['type'] == 'Ignore':
return return
@ -1413,7 +1415,8 @@ def outbox_undo_mute(base_dir: str, http_prefix: str,
if not has_actor(message_json, debug): if not has_actor(message_json, debug):
return return
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
if not message_json['actor'].endswith(domain_full + '/users/' + nickname): actor_url = get_actor_from_post(message_json)
if not actor_url.endswith(domain_full + '/users/' + nickname):
return return
if not message_json['type'] == 'Undo': if not message_json['type'] == 'Undo':
return return

View File

@ -32,6 +32,7 @@ from utils import has_object_string_type
from utils import text_in_file from utils import text_in_file
from utils import remove_eol from utils import remove_eol
from utils import remove_html from utils import remove_html
from utils import get_actor_from_post
from posts import get_person_box from posts import get_person_box
from session import post_json from session import post_json
@ -614,9 +615,10 @@ def outbox_bookmark(recent_posts_cache: {},
print('DEBUG: c2s like post not found in inbox or outbox') print('DEBUG: c2s like post not found in inbox or outbox')
print(message_url) print(message_url)
return True return True
actor_url = get_actor_from_post(message_json)
update_bookmarks_collection(recent_posts_cache, update_bookmarks_collection(recent_posts_cache,
base_dir, post_filename, message_url, base_dir, post_filename, message_url,
message_json['actor'], domain, debug) actor_url, domain, debug)
if debug: if debug:
print('DEBUG: post bookmarked via c2s - ' + post_filename) print('DEBUG: post bookmarked via c2s - ' + post_filename)
@ -673,8 +675,9 @@ def outbox_undo_bookmark(recent_posts_cache: {},
print('DEBUG: c2s unbookmark post not found in inbox or outbox') print('DEBUG: c2s unbookmark post not found in inbox or outbox')
print(message_url) print(message_url)
return True return True
actor_url = get_actor_from_post(message_json)
update_bookmarks_collection(recent_posts_cache, update_bookmarks_collection(recent_posts_cache,
base_dir, post_filename, message_url, base_dir, post_filename, message_url,
message_json['actor'], domain, debug) actor_url, domain, debug)
if debug: if debug:
print('DEBUG: post unbookmarked via c2s - ' + post_filename) print('DEBUG: post unbookmarked via c2s - ' + post_filename)

View File

@ -387,6 +387,7 @@ from utils import refresh_newswire
from utils import is_image_file from utils import is_image_file
from utils import has_group_type from utils import has_group_type
from utils import binary_is_image from utils import binary_is_image
from utils import get_actor_from_post
from manualapprove import manual_deny_follow_request_thread from manualapprove import manual_deny_follow_request_thread
from manualapprove import manual_approve_follow_request_thread from manualapprove import manual_approve_follow_request_thread
from announce import create_announce from announce import create_announce
@ -2178,9 +2179,10 @@ class PubServer(BaseHTTPRequestHandler):
# actor should be a string # actor should be a string
if debug: if debug:
print('INBOX: checking that actor is string') print('INBOX: checking that actor is string')
if not isinstance(message_json['actor'], str): actor_url = get_actor_from_post(message_json)
if not isinstance(actor_url, str):
print('INBOX: ' + print('INBOX: ' +
'actor should be a string ' + str(message_json['actor'])) 'actor should be a string ' + str(actor_url))
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
@ -2262,8 +2264,9 @@ class PubServer(BaseHTTPRequestHandler):
if message_json['object'].get('content'): if message_json['object'].get('content'):
content_str = message_json['object']['content'] content_str = message_json['object']['content']
if not valid_url_lengths(content_str, 2048): if not valid_url_lengths(content_str, 2048):
actor_url = get_actor_from_post(message_json)
print('INBOX: content contains urls which are too long ' + print('INBOX: content contains urls which are too long ' +
message_json['actor']) actor_url)
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
@ -2274,23 +2277,26 @@ class PubServer(BaseHTTPRequestHandler):
message_json['object']['type'] != 'Application' and \ message_json['object']['type'] != 'Application' and \
message_json['object']['type'] != 'Group': message_json['object']['type'] != 'Group':
if len(message_json['object']['summary']) > 1024: if len(message_json['object']['summary']) > 1024:
actor_url = get_actor_from_post(message_json)
print('INBOX: summary is too long ' + print('INBOX: summary is too long ' +
message_json['actor'] + ' ' + actor_url + ' ' +
message_json['object']['summary']) message_json['object']['summary'])
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
if '://' in message_json['object']['summary']: if '://' in message_json['object']['summary']:
actor_url = get_actor_from_post(message_json)
print('INBOX: summary should not contain links ' + print('INBOX: summary should not contain links ' +
message_json['actor'] + ' ' + actor_url + ' ' +
message_json['object']['summary']) message_json['object']['summary'])
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
else: else:
if len(message_json['object']['summary']) > 4096: if len(message_json['object']['summary']) > 4096:
actor_url = get_actor_from_post(message_json)
print('INBOX: person summary is too long ' + print('INBOX: person summary is too long ' +
message_json['actor'] + ' ' + actor_url + ' ' +
message_json['object']['summary']) message_json['object']['summary'])
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
@ -2335,10 +2341,11 @@ class PubServer(BaseHTTPRequestHandler):
# actor should look like a url # actor should look like a url
if debug: if debug:
print('INBOX: checking that actor looks like a url') print('INBOX: checking that actor looks like a url')
if '://' not in message_json['actor'] or \ actor_url = get_actor_from_post(message_json)
'.' not in message_json['actor']: if '://' not in actor_url or \
'.' not in actor_url:
print('INBOX: POST actor does not look like a url ' + print('INBOX: POST actor does not look like a url ' +
message_json['actor']) actor_url)
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
@ -2348,18 +2355,19 @@ class PubServer(BaseHTTPRequestHandler):
print('INBOX: checking for local network access') print('INBOX: checking for local network access')
if not self.server.allow_local_network_access: if not self.server.allow_local_network_access:
local_network_pattern_list = get_local_network_addresses() local_network_pattern_list = get_local_network_addresses()
actor_url = get_actor_from_post(message_json)
for local_network_pattern in local_network_pattern_list: for local_network_pattern in local_network_pattern_list:
if local_network_pattern in message_json['actor']: if local_network_pattern in actor_url:
print('INBOX: POST actor contains local network address ' + print('INBOX: POST actor contains local network address ' +
message_json['actor']) actor_url)
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
message_domain, _ = \ actor_url = get_actor_from_post(message_json)
get_domain_from_actor(message_json['actor']) message_domain, _ = get_domain_from_actor(actor_url)
if not message_domain: if not message_domain:
print('INBOX: POST from unknown domain ' + message_json['actor']) print('INBOX: POST from unknown domain ' + actor_url)
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
@ -2379,10 +2387,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
message_nickname = \ message_nickname = get_nickname_from_actor(actor_url)
get_nickname_from_actor(message_json['actor'])
if not message_nickname: if not message_nickname:
print('INBOX: POST from unknown nickname ' + message_json['actor']) print('INBOX: POST from unknown nickname ' + actor_url)
self._400() self._400()
self.server.postreq_busy = False self.server.postreq_busy = False
return 3 return 3
@ -2402,7 +2409,7 @@ class PubServer(BaseHTTPRequestHandler):
if message_domain: if message_domain:
print('INBOX: Queue: ' + print('INBOX: Queue: ' +
'Inbox queue is full. Incoming post from ' + 'Inbox queue is full. Incoming post from ' +
message_json['actor']) actor_url)
else: else:
print('INBOX: Queue: Inbox queue is full') print('INBOX: Queue: Inbox queue is full')
self._503() self._503()

View File

@ -23,6 +23,7 @@ from utils import remove_moderation_post_from_index
from utils import local_actor_url from utils import local_actor_url
from utils import date_utcnow from utils import date_utcnow
from utils import date_epoch from utils import date_epoch
from utils import get_actor_from_post
from session import post_json from session import post_json
from webfinger import webfinger_handle from webfinger import webfinger_handle
from auth import create_basic_auth_header from auth import create_basic_auth_header
@ -138,9 +139,10 @@ def outbox_delete(base_dir: str, http_prefix: str,
if debug: if debug:
print('DEBUG: c2s delete request arrived in outbox') print('DEBUG: c2s delete request arrived in outbox')
delete_prefix = http_prefix + '://' + domain delete_prefix = http_prefix + '://' + domain
actor_url = get_actor_from_post(message_json)
if (not allow_deletion and if (not allow_deletion and
(not message_json['object'].startswith(delete_prefix) or (not message_json['object'].startswith(delete_prefix) or
not message_json['actor'].startswith(delete_prefix))): not actor_url.startswith(delete_prefix))):
if debug: if debug:
print('DEBUG: delete not permitted from other instances') print('DEBUG: delete not permitted from other instances')
return return

View File

@ -34,6 +34,7 @@ from utils import get_domain_from_actor
from utils import is_pgp_encrypted from utils import is_pgp_encrypted
from utils import local_actor_url from utils import local_actor_url
from utils import get_reply_to from utils import get_reply_to
from utils import get_actor_from_post
from session import create_session from session import create_session
from speaker import speakable_text from speaker import speakable_text
from speaker import get_speaker_pitch from speaker import get_speaker_pitch
@ -801,7 +802,7 @@ def _read_local_box_post(session, nickname: str, domain: str,
print('') print('')
if post_json_object['type'] == 'Announce': if post_json_object['type'] == 'Announce':
actor = post_json_object['actor'] actor = get_actor_from_post(post_json_object)
name_str = get_nickname_from_actor(actor) name_str = get_nickname_from_actor(actor)
recent_posts_cache = {} recent_posts_cache = {}
allow_local_network_access = False allow_local_network_access = False
@ -1142,7 +1143,8 @@ def _desktop_show_box(indent: str,
if post_json_object.get('actor') and \ if post_json_object.get('actor') and \
post_json_object.get('object'): post_json_object.get('object'):
if isinstance(post_json_object['object'], str): if isinstance(post_json_object['object'], str):
author_actor = post_json_object['actor'] author_actor = \
get_actor_from_post(post_json_object)
name = get_nickname_from_actor(author_actor) + '' name = get_nickname_from_actor(author_actor) + ''
name = _pad_to_width(name, name_width) name = _pad_to_width(name, name_width)
ctr_str = str(ctr) ctr_str = str(ctr)

View File

@ -33,6 +33,7 @@ from utils import has_group_type
from utils import local_actor_url from utils import local_actor_url
from utils import text_in_file from utils import text_in_file
from utils import remove_eol from utils import remove_eol
from utils import get_actor_from_post
from acceptreject import create_accept from acceptreject import create_accept
from acceptreject import create_reject from acceptreject import create_reject
from webfinger import webfinger_handle from webfinger import webfinger_handle
@ -803,7 +804,8 @@ def followed_account_accepts(session, base_dir: str, http_prefix: str,
group_account = False group_account = False
if follow_json: if follow_json:
if follow_json.get('actor'): if follow_json.get('actor'):
if has_group_type(base_dir, follow_json['actor'], person_cache): actor_url = get_actor_from_post(follow_json)
if has_group_type(base_dir, actor_url, person_cache):
group_account = True group_account = True
extra_headers = {} extra_headers = {}
@ -858,7 +860,7 @@ def followed_account_rejects(session, session_onion, session_i2p,
follow_activity_filename) follow_activity_filename)
return None return None
# actor who made the follow request # actor who made the follow request
person_url = follow_json['actor'] person_url = get_actor_from_post(follow_json)
# create the reject activity # create the reject activity
reject_json = \ reject_json = \
@ -1474,17 +1476,15 @@ def outbox_undo_follow(base_dir: str, message_json: {}, debug: bool) -> None:
if debug: if debug:
print('DEBUG: undo follow arrived in outbox') print('DEBUG: undo follow arrived in outbox')
nickname_follower = \ actor_url = get_actor_from_post(message_json['object'])
get_nickname_from_actor(message_json['object']['actor']) nickname_follower = get_nickname_from_actor(actor_url)
if not nickname_follower: if not nickname_follower:
print('WARN: unable to find nickname in ' + print('WARN: unable to find nickname in ' +
message_json['object']['actor']) actor_url)
return return
domain_follower, port_follower = \ domain_follower, port_follower = get_domain_from_actor(actor_url)
get_domain_from_actor(message_json['object']['actor'])
if not domain_follower: if not domain_follower:
print('WARN: unable to find domain in ' + print('WARN: unable to find domain in ' + actor_url)
message_json['object']['actor'])
return return
domain_follower_full = get_full_domain(domain_follower, port_follower) domain_follower_full = get_full_domain(domain_follower, port_follower)

170
inbox.py
View File

@ -81,6 +81,7 @@ from utils import has_object_string_type
from utils import valid_hash_tag from utils import valid_hash_tag
from utils import get_attributed_to from utils import get_attributed_to
from utils import get_reply_to from utils import get_reply_to
from utils import get_actor_from_post
from categories import get_hashtag_categories from categories import get_hashtag_categories
from categories import set_hashtag_category from categories import set_hashtag_category
from httpsig import get_digest_algorithm_from_headers from httpsig import get_digest_algorithm_from_headers
@ -272,7 +273,7 @@ def _store_last_post_id(base_dir: str, nickname: str, domain: str,
actor = actor_str actor = actor_str
post_id = remove_id_ending(post_json_object['object']['id']) post_id = remove_id_ending(post_json_object['object']['id'])
if not actor: if not actor:
actor = post_json_object['actor'] actor = get_actor_from_post(post_json_object)
post_id = remove_id_ending(post_json_object['id']) post_id = remove_id_ending(post_json_object['id'])
if not actor: if not actor:
return return
@ -573,15 +574,16 @@ def inbox_message_has_params(message_json: {}) -> bool:
return False return False
# actor should be a string # actor should be a string
if not isinstance(message_json['actor'], str): actor_url = get_actor_from_post(message_json)
if not actor_url:
print('WARN: actor should be a string, but is actually: ' + print('WARN: actor should be a string, but is actually: ' +
str(message_json['actor'])) actor_url)
pprint(message_json) pprint(message_json)
return False return False
# type should be a string # type should be a string
if not isinstance(message_json['type'], str): if not isinstance(message_json['type'], str):
print('WARN: type from ' + str(message_json['actor']) + print('WARN: type from ' + actor_url +
' should be a string, but is actually: ' + ' should be a string, but is actually: ' +
str(message_json['type'])) str(message_json['type']))
return False return False
@ -589,7 +591,7 @@ def inbox_message_has_params(message_json: {}) -> bool:
# object should be a dict or a string # object should be a dict or a string
if not has_object_dict(message_json): if not has_object_dict(message_json):
if not isinstance(message_json['object'], str): if not isinstance(message_json['object'], str):
print('WARN: object from ' + str(message_json['actor']) + print('WARN: object from ' + actor_url +
' should be a dict or string, but is actually: ' + ' should be a dict or string, but is actually: ' +
str(message_json['object'])) str(message_json['object']))
return False return False
@ -611,7 +613,7 @@ def inbox_permitted_message(domain: str, message_json: {},
if not has_actor(message_json, False): if not has_actor(message_json, False):
return False return False
actor = message_json['actor'] actor = get_actor_from_post(message_json)
# always allow the local domain # always allow the local domain
if domain in actor: if domain in actor:
return True return True
@ -703,7 +705,7 @@ def save_post_to_inbox_queue(base_dir: str, http_prefix: str,
get_attributed_to(post_json_object['object']['attributedTo']) get_attributed_to(post_json_object['object']['attributedTo'])
if not sending_actor: if not sending_actor:
if post_json_object.get('actor'): if post_json_object.get('actor'):
sending_actor = post_json_object['actor'] sending_actor = get_actor_from_post(post_json_object)
# check that the sender is valid # check that the sender is valid
if sending_actor: if sending_actor:
@ -948,7 +950,7 @@ def _inbox_post_recipients(base_dir: str, post_json_object: {},
domain = get_full_domain(domain, port) domain = get_full_domain(domain, port)
domain_match = '/' + domain + '/users/' domain_match = '/' + domain + '/users/'
actor = post_json_object['actor'] actor = get_actor_from_post(post_json_object)
# first get any specific people which the post is addressed to # first get any specific people which the post is addressed to
follower_recipients = False follower_recipients = False
@ -1062,13 +1064,13 @@ def _receive_undo_follow(base_dir: str, message_json: {},
if debug: if debug:
print('DEBUG: undo follow request has no actor within object') print('DEBUG: undo follow request has no actor within object')
return False return False
actor = message_json['object']['actor'] actor = get_actor_from_post(message_json['object'])
if not has_users_path(actor): if not has_users_path(actor):
if debug: if debug:
print('DEBUG: undo follow request "users" or "profile" missing ' + print('DEBUG: undo follow request "users" or "profile" missing ' +
'from actor within object') 'from actor within object')
return False return False
if actor != message_json['actor']: if actor != get_actor_from_post(message_json):
if debug: if debug:
print('DEBUG: undo follow request actors do not match') print('DEBUG: undo follow request actors do not match')
return False return False
@ -1146,7 +1148,8 @@ def _receive_undo(base_dir: str, message_json: {}, debug: bool,
print('DEBUG: Undo activity received') print('DEBUG: Undo activity received')
if not has_actor(message_json, debug): if not has_actor(message_json, debug):
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor') print('DEBUG: "users" or "profile" missing from actor')
return False return False
@ -1366,7 +1369,9 @@ def _receive_update_to_question(recent_posts_cache: {}, message_json: {},
if dangerous_question(post_json_object, allow_local_network_access): if dangerous_question(post_json_object, allow_local_network_access):
return False return False
# does the actor match? # does the actor match?
if post_json_object['actor'] != message_json['actor']: actor_url = get_actor_from_post(post_json_object)
actor_url2 = get_actor_from_post(message_json)
if actor_url != actor_url2:
return False return False
save_json(message_json, post_filename) save_json(message_json, post_filename)
# ensure that the cached post is removed if it exists, so # ensure that the cached post is removed if it exists, so
@ -1616,9 +1621,11 @@ def receive_edit_to_post(recent_posts_cache: {}, message_json: {},
if 'content' not in message_json['object']: if 'content' not in message_json['object']:
return False return False
# does the actor match? # does the actor match?
if post_json_object['actor'] != message_json['actor']: actor_url = get_actor_from_post(post_json_object)
actor_url2 = get_actor_from_post(message_json)
if actor_url != actor_url2:
print('EDITPOST: actors do not match ' + print('EDITPOST: actors do not match ' +
post_json_object['actor'] + ' != ' + message_json['actor']) actor_url + ' != ' + actor_url2)
return False return False
# has the content changed? # has the content changed?
if post_json_object['object']['content'] == \ if post_json_object['object']['content'] == \
@ -1755,13 +1762,14 @@ def _receive_move_activity(session, base_dir: str,
str(message_json['target'])) str(message_json['target']))
return False return False
previous_actor = None previous_actor = None
if message_json['object'] == message_json['actor']: actor_url = get_actor_from_post(message_json)
if message_json['object'] == actor_url:
print('INBOX: Move activity sent by old actor ' + print('INBOX: Move activity sent by old actor ' +
message_json['actor'] + ' moving to ' + message_json['target']) actor_url + ' moving to ' + message_json['target'])
previous_actor = message_json['actor'] previous_actor = actor_url
elif message_json['target'] == message_json['actor']: elif message_json['target'] == actor_url:
print('INBOX: Move activity sent by new actor ' + print('INBOX: Move activity sent by new actor ' +
message_json['actor'] + ' moving from ' + actor_url + ' moving from ' +
message_json['object']) message_json['object'])
previous_actor = message_json['object'] previous_actor = message_json['object']
if not previous_actor: if not previous_actor:
@ -1846,7 +1854,8 @@ def _receive_update_activity(recent_posts_cache: {}, session, base_dir: str,
return False return False
if not has_object_string_type(message_json, debug): if not has_object_string_type(message_json, debug):
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type']) message_json['type'])
@ -1895,9 +1904,10 @@ def _receive_update_activity(recent_posts_cache: {}, session, base_dir: str,
message_json['object'].get('id'): message_json['object'].get('id'):
if debug: if debug:
print('Request to update actor: ' + str(message_json)) print('Request to update actor: ' + str(message_json))
update_nickname = get_nickname_from_actor(message_json['actor']) actor_url = get_actor_from_post(message_json)
update_nickname = get_nickname_from_actor(actor_url)
update_domain, update_port = \ update_domain, update_port = \
get_domain_from_actor(message_json['actor']) get_domain_from_actor(actor_url)
if update_nickname and update_domain: if update_nickname and update_domain:
if _person_receive_update(base_dir, if _person_receive_update(base_dir,
domain, port, domain, port,
@ -1945,7 +1955,8 @@ def _receive_like(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: ' + message_json['type'] + ' has no "to" list') print('DEBUG: ' + message_json['type'] + ' has no "to" list')
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type']) message_json['type'])
@ -1972,7 +1983,7 @@ def _receive_like(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: liked post found in inbox') print('DEBUG: liked post found in inbox')
like_actor = message_json['actor'] like_actor = get_actor_from_post(message_json)
handle_name = handle.split('@')[0] handle_name = handle.split('@')[0]
handle_dom = handle.split('@')[1] handle_dom = handle.split('@')[1]
if not _already_liked(base_dir, if not _already_liked(base_dir,
@ -2081,7 +2092,8 @@ def _receive_undo_like(recent_posts_cache: {},
return False return False
if not has_object_string_object(message_json, debug): if not has_object_string_object(message_json, debug):
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + ' like') message_json['type'] + ' like')
@ -2107,7 +2119,7 @@ def _receive_undo_like(recent_posts_cache: {},
return True return True
if debug: if debug:
print('DEBUG: liked post found in inbox. Now undoing.') print('DEBUG: liked post found in inbox. Now undoing.')
like_actor = message_json['actor'] like_actor = get_actor_from_post(message_json)
post_liked_id = message_json['object'] post_liked_id = message_json['object']
undo_likes_collection_entry(recent_posts_cache, base_dir, post_filename, undo_likes_collection_entry(recent_posts_cache, base_dir, post_filename,
post_liked_id, like_actor, domain, debug, None) post_liked_id, like_actor, domain, debug, None)
@ -2213,11 +2225,12 @@ def _receive_reaction(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: ' + message_json['type'] + ' content is not string') print('DEBUG: ' + message_json['type'] + ' content is not string')
return False return False
actor_url = get_actor_from_post(message_json)
if not valid_emoji_content(message_json['content']): if not valid_emoji_content(message_json['content']):
print('_receive_reaction: Invalid emoji reaction: "' + print('_receive_reaction: Invalid emoji reaction: "' +
message_json['content'] + '" from ' + message_json['actor']) message_json['content'] + '" from ' + actor_url)
return False return False
if not has_users_path(message_json['actor']): if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type']) message_json['type'])
@ -2254,7 +2267,7 @@ def _receive_reaction(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: emoji reaction post found in inbox') print('DEBUG: emoji reaction post found in inbox')
reaction_actor = message_json['actor'] reaction_actor = get_actor_from_post(message_json)
handle_name = handle.split('@')[0] handle_name = handle.split('@')[0]
handle_dom = handle.split('@')[1] handle_dom = handle.split('@')[1]
if not _already_reacted(base_dir, if not _already_reacted(base_dir,
@ -2394,12 +2407,13 @@ def _receive_zot_reaction(recent_posts_cache: {},
print('DEBUG: ' + message_json['object']['type'] + print('DEBUG: ' + message_json['object']['type'] +
' inReplyTo is not string') ' inReplyTo is not string')
return False return False
actor_url = get_actor_from_post(message_json)
if not valid_emoji_content(message_json['object']['content']): if not valid_emoji_content(message_json['object']['content']):
print('_receive_zot_reaction: Invalid emoji reaction: "' + print('_receive_zot_reaction: Invalid emoji reaction: "' +
message_json['object']['content'] + '" from ' + message_json['object']['content'] + '" from ' +
message_json['actor']) actor_url)
return False return False
if not has_users_path(message_json['actor']): if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['object']['type']) message_json['object']['type'])
@ -2437,7 +2451,7 @@ def _receive_zot_reaction(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: zot emoji reaction post found in inbox') print('DEBUG: zot emoji reaction post found in inbox')
reaction_actor = message_json['actor'] reaction_actor = get_actor_from_post(message_json)
handle_name = handle.split('@')[0] handle_name = handle.split('@')[0]
handle_dom = handle.split('@')[1] handle_dom = handle.split('@')[1]
if not _already_reacted(base_dir, if not _already_reacted(base_dir,
@ -2560,7 +2574,8 @@ def _receive_undo_reaction(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: ' + message_json['type'] + ' content is not string') print('DEBUG: ' + message_json['type'] + ' content is not string')
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + ' reaction') message_json['type'] + ' reaction')
@ -2586,7 +2601,7 @@ def _receive_undo_reaction(recent_posts_cache: {},
return True return True
if debug: if debug:
print('DEBUG: reaction post found in inbox. Now undoing.') print('DEBUG: reaction post found in inbox. Now undoing.')
reaction_actor = message_json['actor'] reaction_actor = actor_url
post_reaction_id = message_json['object'] post_reaction_id = message_json['object']
emoji_content = remove_html(message_json['object']['content']) emoji_content = remove_html(message_json['object']['content'])
if not emoji_content: if not emoji_content:
@ -2704,11 +2719,12 @@ def _receive_bookmark(recent_posts_cache: {},
return False return False
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
nickname = handle.split('@')[0] nickname = handle.split('@')[0]
if not message_json['actor'].endswith(domain_full + '/users/' + nickname): actor_url = get_actor_from_post(message_json)
if not actor_url.endswith(domain_full + '/users/' + nickname):
if debug: if debug:
print('DEBUG: inbox bookmark Add unexpected actor') print('DEBUG: inbox bookmark Add unexpected actor')
return False return False
if not message_json['target'].endswith(message_json['actor'] + if not message_json['target'].endswith(actor_url +
'/tlbookmarks'): '/tlbookmarks'):
if debug: if debug:
print('DEBUG: inbox bookmark Add target invalid ' + print('DEBUG: inbox bookmark Add target invalid ' +
@ -2741,8 +2757,7 @@ def _receive_bookmark(recent_posts_cache: {},
return True return True
update_bookmarks_collection(recent_posts_cache, base_dir, post_filename, update_bookmarks_collection(recent_posts_cache, base_dir, post_filename,
message_url2, message_url2, actor_url, domain, debug)
message_json['actor'], domain, debug)
# regenerate the html # regenerate the html
bookmarked_post_json = load_json(post_filename, 0, 1) bookmarked_post_json = load_json(post_filename, 0, 1)
if bookmarked_post_json: if bookmarked_post_json:
@ -2831,11 +2846,12 @@ def _receive_undo_bookmark(recent_posts_cache: {},
return False return False
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
nickname = handle.split('@')[0] nickname = handle.split('@')[0]
if not message_json['actor'].endswith(domain_full + '/users/' + nickname): actor_url = get_actor_from_post(message_json)
if not actor_url.endswith(domain_full + '/users/' + nickname):
if debug: if debug:
print('DEBUG: inbox undo bookmark Remove unexpected actor') print('DEBUG: inbox undo bookmark Remove unexpected actor')
return False return False
if not message_json['target'].endswith(message_json['actor'] + if not message_json['target'].endswith(actor_url +
'/tlbookmarks'): '/tlbookmarks'):
if debug: if debug:
print('DEBUG: inbox undo bookmark Remove target invalid ' + print('DEBUG: inbox undo bookmark Remove target invalid ' +
@ -2870,7 +2886,7 @@ def _receive_undo_bookmark(recent_posts_cache: {},
undo_bookmarks_collection_entry(recent_posts_cache, base_dir, undo_bookmarks_collection_entry(recent_posts_cache, base_dir,
post_filename, post_filename,
message_json['actor'], domain, debug) actor_url, domain, debug)
# regenerate the html # regenerate the html
bookmarked_post_json = load_json(post_filename, 0, 1) bookmarked_post_json = load_json(post_filename, 0, 1)
if bookmarked_post_json: if bookmarked_post_json:
@ -2936,9 +2952,10 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
return False return False
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
delete_prefix = http_prefix + '://' + domain_full + '/' delete_prefix = http_prefix + '://' + domain_full + '/'
actor_url = get_actor_from_post(message_json)
if (not allow_deletion and if (not allow_deletion and
(not message_json['object'].startswith(delete_prefix) or (not message_json['object'].startswith(delete_prefix) or
not message_json['actor'].startswith(delete_prefix))): not actor_url.startswith(delete_prefix))):
if debug: if debug:
print('DEBUG: delete not permitted from other instances') print('DEBUG: delete not permitted from other instances')
return False return False
@ -2946,7 +2963,7 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
if debug: if debug:
print('DEBUG: ' + message_json['type'] + ' has no "to" list') print('DEBUG: ' + message_json['type'] + ' has no "to" list')
return False return False
if not has_users_path(message_json['actor']): if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: ' + print('DEBUG: ' +
'"users" or "profile" missing from actor in ' + '"users" or "profile" missing from actor in ' +
@ -2957,7 +2974,7 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
print('DEBUG: "statuses" missing from object in ' + print('DEBUG: "statuses" missing from object in ' +
message_json['type']) message_json['type'])
return False return False
if message_json['actor'] not in message_json['object']: if actor_url not in message_json['object']:
if debug: if debug:
print('DEBUG: actor is not the owner of the post to be deleted') print('DEBUG: actor is not the owner of the post to be deleted')
handle_dir = acct_handle_dir(base_dir, handle) handle_dir = acct_handle_dir(base_dir, handle)
@ -3034,7 +3051,8 @@ def _receive_announce(recent_posts_cache: {},
if debug: if debug:
print('DEBUG: ' + message_json['type'] + ' has no "to" list') print('DEBUG: ' + message_json['type'] + ' has no "to" list')
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: ' + print('DEBUG: ' +
'"users" or "profile" missing from actor in ' + '"users" or "profile" missing from actor in ' +
@ -3069,11 +3087,11 @@ def _receive_announce(recent_posts_cache: {},
# is the announce actor blocked? # is the announce actor blocked?
nickname = handle.split('@')[0] nickname = handle.split('@')[0]
actor_nickname = get_nickname_from_actor(message_json['actor']) actor_nickname = get_nickname_from_actor(actor_url)
if not actor_nickname: if not actor_nickname:
print('WARN: _receive_announce no actor_nickname') print('WARN: _receive_announce no actor_nickname')
return False return False
actor_domain, _ = get_domain_from_actor(message_json['actor']) actor_domain, _ = get_domain_from_actor(actor_url)
if not actor_domain: if not actor_domain:
print('WARN: _receive_announce no actor_domain') print('WARN: _receive_announce no actor_domain')
return False return False
@ -3117,10 +3135,11 @@ def _receive_announce(recent_posts_cache: {},
print(message_json['object']) print(message_json['object'])
return True return True
# add actor to the list of announcers for a post # add actor to the list of announcers for a post
actor_url = get_actor_from_post(message_json)
update_announce_collection(recent_posts_cache, base_dir, post_filename, update_announce_collection(recent_posts_cache, base_dir, post_filename,
message_json['actor'], nickname, domain, debug) actor_url, nickname, domain, debug)
if debug: if debug:
print('DEBUG: Downloading announce post ' + message_json['actor'] + print('DEBUG: Downloading announce post ' + actor_url +
' -> ' + message_json['object']) ' -> ' + message_json['object'])
domain_full = get_full_domain(domain, port) domain_full = get_full_domain(domain, port)
@ -3215,8 +3234,9 @@ def _receive_announce(recent_posts_cache: {},
str(post_filename)) str(post_filename))
else: else:
if debug: if debug:
actor_url = get_actor_from_post(message_json)
print('DEBUG: Announce post downloaded for ' + print('DEBUG: Announce post downloaded for ' +
message_json['actor'] + ' -> ' + message_json['object']) actor_url + ' -> ' + message_json['object'])
store_hash_tags(base_dir, nickname, domain, store_hash_tags(base_dir, nickname, domain,
http_prefix, domain_full, http_prefix, domain_full,
post_json_object, translate) post_json_object, translate)
@ -3309,7 +3329,8 @@ def _receive_undo_announce(recent_posts_cache: {},
return False return False
if message_json['object']['type'] != 'Announce': if message_json['object']['type'] != 'Announce':
return False return False
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: "users" or "profile" missing from actor in ' + print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + ' announce') message_json['type'] + ' announce')
@ -3339,7 +3360,7 @@ def _receive_undo_announce(recent_posts_cache: {},
"which isn't an announcement") "which isn't an announcement")
return False return False
undo_announce_collection_entry(recent_posts_cache, base_dir, post_filename, undo_announce_collection_entry(recent_posts_cache, base_dir, post_filename,
message_json['actor'], domain, debug) actor_url, domain, debug)
if os.path.isfile(post_filename): if os.path.isfile(post_filename):
try: try:
os.remove(post_filename) os.remove(post_filename)
@ -3936,7 +3957,7 @@ def _inbox_update_calendar_from_tag(base_dir: str, handle: str,
if not isinstance(post_json_object['object']['tag'], list): if not isinstance(post_json_object['object']['tag'], list):
return return
actor = post_json_object['actor'] actor = get_actor_from_post(post_json_object)
actor_nickname = get_nickname_from_actor(actor) actor_nickname = get_nickname_from_actor(actor)
if not actor_nickname: if not actor_nickname:
return return
@ -3981,7 +4002,7 @@ def _inbox_update_calendar_from_event(base_dir: str, handle: str,
if not isinstance(post_json_object['object']['startTime'], str): if not isinstance(post_json_object['object']['startTime'], str):
return return
actor = post_json_object['actor'] actor = get_actor_from_post(post_json_object)
actor_nickname = get_nickname_from_actor(actor) actor_nickname = get_nickname_from_actor(actor)
if not actor_nickname: if not actor_nickname:
return return
@ -4210,7 +4231,7 @@ def _is_valid_dm(base_dir: str, nickname: str, domain: str, port: int,
# who is sending a DM? # who is sending a DM?
if not post_json_object.get('actor'): if not post_json_object.get('actor'):
return False return False
sending_actor = post_json_object['actor'] sending_actor = get_actor_from_post(post_json_object)
sending_actor_nickname = \ sending_actor_nickname = \
get_nickname_from_actor(sending_actor) get_nickname_from_actor(sending_actor)
if not sending_actor_nickname: if not sending_actor_nickname:
@ -5573,16 +5594,17 @@ def _receive_follow_request(session, session_onion, session_i2p,
print('Receiving follow request') print('Receiving follow request')
if not has_actor(message_json, debug): if not has_actor(message_json, debug):
return True return True
if not has_users_path(message_json['actor']): actor_url = get_actor_from_post(message_json)
if not has_users_path(actor_url):
if debug: if debug:
print('DEBUG: ' + print('DEBUG: ' +
'users/profile/author/accounts/channel missing from actor') 'users/profile/author/accounts/channel missing from actor')
return True return True
domain, temp_port = get_domain_from_actor(message_json['actor']) domain, temp_port = get_domain_from_actor(actor_url)
if not domain: if not domain:
if debug: if debug:
print('DEBUG: receive follow request actor without domain ' + print('DEBUG: receive follow request actor without domain ' +
message_json['actor']) actor_url)
return True return True
from_port = port from_port = port
domain_full = get_full_domain(domain, temp_port) domain_full = get_full_domain(domain, temp_port)
@ -5592,7 +5614,7 @@ def _receive_follow_request(session, session_onion, session_i2p,
if debug: if debug:
print('DEBUG: follower from domain not permitted - ' + domain) print('DEBUG: follower from domain not permitted - ' + domain)
return True return True
nickname = get_nickname_from_actor(message_json['actor']) nickname = get_nickname_from_actor(actor_url)
if not nickname: if not nickname:
# single user instance # single user instance
nickname = 'dev' nickname = 'dev'
@ -5723,10 +5745,10 @@ def _receive_follow_request(session, session_onion, session_i2p,
# Get the actor for the follower and add it to the cache. # Get the actor for the follower and add it to the cache.
# Getting their public key has the same result # Getting their public key has the same result
if debug: if debug:
print('Obtaining the following actor: ' + message_json['actor']) print('Obtaining the following actor: ' + actor_url)
pubkey_result = \ pubkey_result = \
get_person_pub_key(base_dir, curr_session, get_person_pub_key(base_dir, curr_session,
message_json['actor'], actor_url,
person_cache, debug, project_version, person_cache, debug, project_version,
curr_http_prefix, curr_http_prefix,
this_domain, onion_domain, this_domain, onion_domain,
@ -5734,14 +5756,14 @@ def _receive_follow_request(session, session_onion, session_i2p,
if not pubkey_result: if not pubkey_result:
if debug: if debug:
print('Unable to obtain following actor: ' + print('Unable to obtain following actor: ' +
message_json['actor']) actor_url)
elif isinstance(pubkey_result, dict): elif isinstance(pubkey_result, dict):
if debug: if debug:
print('http error code trying to obtain following actor: ' + print('http error code trying to obtain following actor: ' +
message_json['actor'] + ' ' + str(pubkey_result)) actor_url + ' ' + str(pubkey_result))
group_account = \ group_account = \
has_group_type(base_dir, message_json['actor'], person_cache) has_group_type(base_dir, actor_url, person_cache)
if group_account and is_group_account(base_dir, nickname, domain): if group_account and is_group_account(base_dir, nickname, domain):
print('Group cannot follow a group') print('Group cannot follow a group')
return True return True
@ -5750,7 +5772,7 @@ def _receive_follow_request(session, session_onion, session_i2p,
return store_follow_request(base_dir, return store_follow_request(base_dir,
nickname_to_follow, domain_to_follow, port, nickname_to_follow, domain_to_follow, port,
nickname, domain, from_port, nickname, domain, from_port,
message_json, debug, message_json['actor'], message_json, debug, actor_url,
group_account) group_account)
else: else:
if is_already_follower: if is_already_follower:
@ -5767,17 +5789,17 @@ def _receive_follow_request(session, session_onion, session_i2p,
# for actors which don't follow the mastodon # for actors which don't follow the mastodon
# /users/ path convention store the full actor # /users/ path convention store the full actor
if '/users/' not in message_json['actor']: if '/users/' not in actor_url:
approve_handle = message_json['actor'] approve_handle = actor_url
# Get the actor for the follower and add it to the cache. # Get the actor for the follower and add it to the cache.
# Getting their public key has the same result # Getting their public key has the same result
if debug: if debug:
print('Obtaining the following actor: ' + print('Obtaining the following actor: ' +
message_json['actor']) actor_url)
pubkey_result = \ pubkey_result = \
get_person_pub_key(base_dir, curr_session, get_person_pub_key(base_dir, curr_session,
message_json['actor'], actor_url,
person_cache, debug, project_version, person_cache, debug, project_version,
curr_http_prefix, this_domain, curr_http_prefix, this_domain,
onion_domain, i2p_domain, onion_domain, i2p_domain,
@ -5785,11 +5807,11 @@ def _receive_follow_request(session, session_onion, session_i2p,
if not pubkey_result: if not pubkey_result:
if debug: if debug:
print('Unable to obtain following actor: ' + print('Unable to obtain following actor: ' +
message_json['actor']) actor_url)
elif isinstance(pubkey_result, dict): elif isinstance(pubkey_result, dict):
if debug: if debug:
print('http error code trying to obtain ' + print('http error code trying to obtain ' +
'following actor: ' + message_json['actor'] + 'following actor: ' + actor_url +
' ' + str(pubkey_result)) ' ' + str(pubkey_result))
print('Updating followers file: ' + print('Updating followers file: ' +
@ -5798,9 +5820,9 @@ def _receive_follow_request(session, session_onion, session_i2p,
if not text_in_file(approve_handle, followers_filename): if not text_in_file(approve_handle, followers_filename):
group_account = \ group_account = \
has_group_type(base_dir, has_group_type(base_dir,
message_json['actor'], person_cache) actor_url, person_cache)
if debug: if debug:
print(approve_handle + ' / ' + message_json['actor'] + print(approve_handle + ' / ' + actor_url +
' is Group: ' + str(group_account)) ' is Group: ' + str(group_account))
if group_account and \ if group_account and \
is_group_account(base_dir, nickname, domain): is_group_account(base_dir, nickname, domain):
@ -5837,7 +5859,7 @@ def _receive_follow_request(session, session_onion, session_i2p,
return followed_account_accepts(curr_session, base_dir, curr_http_prefix, return followed_account_accepts(curr_session, base_dir, curr_http_prefix,
nickname_to_follow, domain_to_follow, port, nickname_to_follow, domain_to_follow, port,
nickname, curr_domain, curr_port, nickname, curr_domain, curr_port,
message_json['actor'], federation_list, actor_url, federation_list,
message_json, send_threads, post_log, message_json, send_threads, post_log,
cached_webfingers, person_cache, cached_webfingers, person_cache,
debug, project_version, True, debug, project_version, True,

10
like.py
View File

@ -28,6 +28,7 @@ from utils import load_json
from utils import save_json from utils import save_json
from utils import remove_post_from_cache from utils import remove_post_from_cache
from utils import get_cached_post_filename from utils import get_cached_post_filename
from utils import get_actor_from_post
from posts import send_signed_json from posts import send_signed_json
from session import post_json from session import post_json
from webfinger import webfinger_handle from webfinger import webfinger_handle
@ -134,9 +135,10 @@ def _create_like(recent_posts_cache: {},
print('DEBUG: like object_url: ' + object_url) print('DEBUG: like object_url: ' + object_url)
return None return None
actor_url = get_actor_from_post(new_like_json)
update_likes_collection(recent_posts_cache, update_likes_collection(recent_posts_cache,
base_dir, post_filename, object_url, base_dir, post_filename, object_url,
new_like_json['actor'], actor_url,
nickname, domain, debug, None) nickname, domain, debug, None)
extra_headers = {} extra_headers = {}
send_signed_json(new_like_json, session, base_dir, send_signed_json(new_like_json, session, base_dir,
@ -388,9 +390,10 @@ def outbox_like(recent_posts_cache: {},
print('DEBUG: c2s like post not found in inbox or outbox') print('DEBUG: c2s like post not found in inbox or outbox')
print(message_id) print(message_id)
return True return True
actor_url = get_actor_from_post(message_json)
update_likes_collection(recent_posts_cache, update_likes_collection(recent_posts_cache,
base_dir, post_filename, message_id, base_dir, post_filename, message_id,
message_json['actor'], actor_url,
nickname, domain, debug, None) nickname, domain, debug, None)
if debug: if debug:
print('DEBUG: post liked via c2s - ' + post_filename) print('DEBUG: post liked via c2s - ' + post_filename)
@ -424,8 +427,9 @@ def outbox_undo_like(recent_posts_cache: {},
print('DEBUG: c2s undo like post not found in inbox or outbox') print('DEBUG: c2s undo like post not found in inbox or outbox')
print(message_id) print(message_id)
return True return True
actor_url = get_actor_from_post(message_json)
undo_likes_collection_entry(recent_posts_cache, base_dir, post_filename, undo_likes_collection_entry(recent_posts_cache, base_dir, post_filename,
message_id, message_json['actor'], message_id, actor_url,
domain, debug, None) domain, debug, None)
if debug: if debug:
print('DEBUG: post undo liked via c2s - ' + post_filename) print('DEBUG: post undo liked via c2s - ' + post_filename)

View File

@ -19,6 +19,7 @@ from utils import get_user_paths
from utils import acct_dir from utils import acct_dir
from utils import text_in_file from utils import text_in_file
from utils import remove_eol from utils import remove_eol
from utils import get_actor_from_post
from threads import thread_with_trace from threads import thread_with_trace
from threads import begin_thread from threads import begin_thread
from session import create_session from session import create_session
@ -276,6 +277,7 @@ def manual_approve_follow_request(session, session_onion, session_i2p,
print('Manual follow accept: Sending Accept for ' + print('Manual follow accept: Sending Accept for ' +
handle + ' follow request from ' + handle + ' follow request from ' +
approve_nickname + '@' + approve_domain) approve_nickname + '@' + approve_domain)
actor_url = get_actor_from_post(follow_json)
followed_account_accepts(curr_session, base_dir, followed_account_accepts(curr_session, base_dir,
curr_http_prefix, curr_http_prefix,
nickname, nickname,
@ -283,7 +285,7 @@ def manual_approve_follow_request(session, session_onion, session_i2p,
approve_nickname, approve_nickname,
approve_domain, approve_domain,
approve_port, approve_port,
follow_json['actor'], actor_url,
federation_list, federation_list,
follow_json, follow_json,
send_threads, post_log, send_threads, post_log,

View File

@ -34,6 +34,7 @@ from utils import acct_dir
from utils import local_actor_url from utils import local_actor_url
from utils import has_actor from utils import has_actor
from utils import is_quote_toot from utils import is_quote_toot
from utils import get_actor_from_post
from blocking import is_blocked_domain from blocking import is_blocked_domain
from blocking import outbox_block from blocking import outbox_block
from blocking import outbox_undo_block from blocking import outbox_undo_block
@ -355,30 +356,31 @@ def post_message_to_outbox(session, translate: {},
return False return False
# actor should be a string # actor should be a string
if not isinstance(message_json['actor'], str): actor_url = get_actor_from_post(message_json)
if not actor_url:
return False return False
# actor should look like a url # actor should look like a url
if '://' not in message_json['actor'] or \ if '://' not in actor_url or \
'.' not in message_json['actor']: '.' not in actor_url:
return False return False
if contains_invalid_actor_url_chars(message_json['actor']): if contains_invalid_actor_url_chars(actor_url):
return False return False
# sent by an actor on a local network address? # sent by an actor on a local network address?
if not allow_local_network_access: if not allow_local_network_access:
local_network_pattern_list = get_local_network_addresses() local_network_pattern_list = get_local_network_addresses()
for local_network_pattern in local_network_pattern_list: for local_network_pattern in local_network_pattern_list:
if local_network_pattern in message_json['actor']: if local_network_pattern in actor_url:
return False return False
test_domain, test_port = get_domain_from_actor(message_json['actor']) test_domain, test_port = get_domain_from_actor(actor_url)
if test_domain: if test_domain:
test_domain = get_full_domain(test_domain, test_port) test_domain = get_full_domain(test_domain, test_port)
if is_blocked_domain(base_dir, test_domain): if is_blocked_domain(base_dir, test_domain):
if debug: if debug:
print('DEBUG: domain is blocked: ' + message_json['actor']) print('DEBUG: domain is blocked: ' + actor_url)
return False return False
# replace youtube, so that google gets less tracking data # replace youtube, so that google gets less tracking data
replace_you_tube(message_json, yt_replace_domain, system_language) replace_you_tube(message_json, yt_replace_domain, system_language)
@ -387,7 +389,7 @@ def post_message_to_outbox(session, translate: {},
replace_twitter(message_json, twitter_replacement_domain, replace_twitter(message_json, twitter_replacement_domain,
system_language) system_language)
# https://www.w3.org/TR/activitypub/#create-activity-outbox # https://www.w3.org/TR/activitypub/#create-activity-outbox
message_json['object']['attributedTo'] = message_json['actor'] message_json['object']['attributedTo'] = actor_url
if message_json['object'].get('attachment'): if message_json['object'].get('attachment'):
attachment_index = 0 attachment_index = 0
attach = message_json['object']['attachment'][attachment_index] attach = message_json['object']['attachment'][attachment_index]
@ -496,10 +498,11 @@ def post_message_to_outbox(session, translate: {},
print('WARN: post not saved to outbox ' + outbox_name) print('WARN: post not saved to outbox ' + outbox_name)
return False return False
actor_url = get_actor_from_post(message_json)
update_speaker(base_dir, http_prefix, update_speaker(base_dir, http_prefix,
post_to_nickname, domain, domain_full, post_to_nickname, domain, domain_full,
message_json, person_cache, message_json, person_cache,
translate, message_json['actor'], translate, actor_url,
theme, system_language, theme, system_language,
outbox_name) outbox_name)

View File

@ -71,6 +71,7 @@ from utils import local_actor_url
from utils import dangerous_svg from utils import dangerous_svg
from utils import text_in_file from utils import text_in_file
from utils import contains_statuses from utils import contains_statuses
from utils import get_actor_from_post
from session import get_json_valid from session import get_json_valid
from session import create_session from session import create_session
from session import get_json from session import get_json
@ -1928,7 +1929,7 @@ def valid_sending_actor(session, base_dir: str,
the sending actor is valid the sending actor is valid
""" """
# who sent this post? # who sent this post?
sending_actor = post_json_object['actor'] sending_actor = get_actor_from_post(post_json_object)
if not isinstance(sending_actor, str): if not isinstance(sending_actor, str):
return False return False

View File

@ -87,6 +87,7 @@ from utils import dangerous_markup
from utils import acct_dir from utils import acct_dir
from utils import local_actor_url from utils import local_actor_url
from utils import get_reply_to from utils import get_reply_to
from utils import get_actor_from_post
from media import get_music_metadata from media import get_music_metadata
from media import attach_media from media import attach_media
from media import replace_you_tube from media import replace_you_tube
@ -3218,7 +3219,8 @@ def _add_followers_to_public_post(post_json_object: {}) -> None:
return return
if post_json_object.get('cc'): if post_json_object.get('cc'):
return return
post_json_object['cc'] = post_json_object['actor'] + '/followers' actor_url = get_actor_from_post(post_json_object)
post_json_object['cc'] = actor_url + '/followers'
elif has_object_dict(post_json_object): elif has_object_dict(post_json_object):
if not post_json_object['object'].get('to'): if not post_json_object['object'].get('to'):
return return
@ -3232,8 +3234,9 @@ def _add_followers_to_public_post(post_json_object: {}) -> None:
return return
if post_json_object['object'].get('cc'): if post_json_object['object'].get('cc'):
return return
actor_url = get_actor_from_post(post_json_object)
post_json_object['object']['cc'] = \ post_json_object['object']['cc'] = \
post_json_object['actor'] + '/followers' actor_url + '/followers'
def send_signed_json(post_json_object: {}, session, base_dir: str, def send_signed_json(post_json_object: {}, session, base_dir: str,
@ -3507,10 +3510,9 @@ def add_to_field(activity_type: str, post_json_object: {},
if post_json_object['type'] == 'Add' or \ if post_json_object['type'] == 'Add' or \
post_json_object['type'] == 'Remove': post_json_object['type'] == 'Remove':
if post_json_object['object']['type'] == 'Document': if post_json_object['object']['type'] == 'Document':
post_json_object['to'] = \ actor_url = get_actor_from_post(post_json_object)
[post_json_object['actor']] post_json_object['to'] = [actor_url]
post_json_object['object']['to'] = \ post_json_object['object']['to'] = [actor_url]
[post_json_object['actor']]
to_field_added = True to_field_added = True
if not to_field_added and \ if not to_field_added and \
@ -5683,7 +5685,8 @@ def download_announce(session, base_dir: str, http_prefix: str,
if not isinstance(post_json_object['object'], str): if not isinstance(post_json_object['object'], str):
return None return None
# ignore self-boosts # ignore self-boosts
if post_json_object['actor'] in post_json_object['object']: actor_url = get_actor_from_post(post_json_object)
if actor_url in post_json_object['object']:
return None return None
# get the announced post # get the announced post
@ -5716,24 +5719,24 @@ def download_announce(session, base_dir: str, http_prefix: str,
as_header = { as_header = {
'Accept': accept_str 'Accept': accept_str
} }
if '/channel/' in post_json_object['actor'] or \ if '/channel/' in actor_url or \
'/accounts/' in post_json_object['actor']: '/accounts/' in actor_url:
accept_str = \ accept_str = \
'application/ld+json; ' + \ 'application/ld+json; ' + \
'profile="' + profile_str + '"' 'profile="' + profile_str + '"'
as_header = { as_header = {
'Accept': accept_str 'Accept': accept_str
} }
actor_nickname = get_nickname_from_actor(post_json_object['actor']) actor_nickname = get_nickname_from_actor(actor_url)
if not actor_nickname: if not actor_nickname:
print('WARN: download_announce no actor_nickname') print('WARN: download_announce no actor_nickname')
return None return None
actor_domain, actor_port = \ actor_domain, actor_port = \
get_domain_from_actor(post_json_object['actor']) get_domain_from_actor(actor_url)
if not actor_domain: if not actor_domain:
print('Announce actor does not contain a ' + print('Announce actor does not contain a ' +
'valid domain or port number: ' + 'valid domain or port number: ' +
str(post_json_object['actor'])) actor_url)
return None return None
if is_blocked(base_dir, nickname, domain, if is_blocked(base_dir, nickname, domain,
actor_nickname, actor_domain): actor_nickname, actor_domain):
@ -6581,7 +6584,7 @@ def get_original_post_from_announce_url(announce_url: str, base_dir: str,
actor = attrib actor = attrib
url = orig_post_id url = orig_post_id
elif orig_post_json['object'].get('actor'): elif orig_post_json['object'].get('actor'):
actor = orig_post_json['actor'] actor = get_actor_from_post(orig_post_json)
url = orig_post_id url = orig_post_id
else: else:
# we don't have the original post # we don't have the original post

View File

@ -15,6 +15,7 @@ from utils import has_object_dict
from utils import text_in_file from utils import text_in_file
from utils import dangerous_markup from utils import dangerous_markup
from utils import get_reply_to from utils import get_reply_to
from utils import get_actor_from_post
def is_vote(base_dir: str, nickname: str, domain: str, def is_vote(base_dir: str, nickname: str, domain: str,
@ -120,23 +121,24 @@ def question_update_votes(base_dir: str, nickname: str, domain: str,
# update the voters file # update the voters file
voters_file_separator = ';;;' voters_file_separator = ';;;'
voters_filename = question_post_filename.replace('.json', '.voters') voters_filename = question_post_filename.replace('.json', '.voters')
actor_url = get_actor_from_post(reply_json)
if not os.path.isfile(voters_filename): if not os.path.isfile(voters_filename):
# create a new voters file # create a new voters file
try: try:
with open(voters_filename, 'w+', with open(voters_filename, 'w+',
encoding='utf-8') as voters_file: encoding='utf-8') as voters_file:
voters_file.write(reply_json['actor'] + voters_file.write(actor_url +
voters_file_separator + voters_file_separator +
reply_vote + '\n') reply_vote + '\n')
except OSError: except OSError:
print('EX: unable to write voters file ' + voters_filename) print('EX: unable to write voters file ' + voters_filename)
else: else:
if not text_in_file(reply_json['actor'], voters_filename): if not text_in_file(actor_url, voters_filename):
# append to the voters file # append to the voters file
try: try:
with open(voters_filename, 'a+', with open(voters_filename, 'a+',
encoding='utf-8') as voters_file: encoding='utf-8') as voters_file:
voters_file.write(reply_json['actor'] + voters_file.write(actor_url +
voters_file_separator + voters_file_separator +
reply_vote + '\n') reply_vote + '\n')
except OSError: except OSError:
@ -149,9 +151,9 @@ def question_update_votes(base_dir: str, nickname: str, domain: str,
newlines = [] newlines = []
save_voters_file = False save_voters_file = False
for vote_line in lines: for vote_line in lines:
if vote_line.startswith(reply_json['actor'] + if vote_line.startswith(actor_url +
voters_file_separator): voters_file_separator):
new_vote_line = reply_json['actor'] + \ new_vote_line = actor_url + \
voters_file_separator + reply_vote + '\n' voters_file_separator + reply_vote + '\n'
if vote_line == new_vote_line: if vote_line == new_vote_line:
break break

View File

@ -32,6 +32,7 @@ from utils import remove_post_from_cache
from utils import get_cached_post_filename from utils import get_cached_post_filename
from utils import contains_invalid_chars from utils import contains_invalid_chars
from utils import remove_eol from utils import remove_eol
from utils import get_actor_from_post
from posts import send_signed_json from posts import send_signed_json
from session import post_json from session import post_json
from webfinger import webfinger_handle from webfinger import webfinger_handle
@ -133,9 +134,10 @@ def _reactionpost(recent_posts_cache: {},
print('DEBUG: reaction object_url: ' + object_url) print('DEBUG: reaction object_url: ' + object_url)
return None return None
actor_url = get_actor_from_post(new_reaction_json)
update_reaction_collection(recent_posts_cache, update_reaction_collection(recent_posts_cache,
base_dir, post_filename, object_url, base_dir, post_filename, object_url,
new_reaction_json['actor'], actor_url,
nickname, domain, debug, None, nickname, domain, debug, None,
emoji_content) emoji_content)
@ -408,9 +410,10 @@ def outbox_reaction(recent_posts_cache: {},
print('DEBUG: c2s reaction post not found in inbox or outbox') print('DEBUG: c2s reaction post not found in inbox or outbox')
print(message_id) print(message_id)
return True return True
actor_url = get_actor_from_post(message_json)
update_reaction_collection(recent_posts_cache, update_reaction_collection(recent_posts_cache,
base_dir, post_filename, message_id, base_dir, post_filename, message_id,
message_json['actor'], actor_url,
nickname, domain, debug, None, emoji_content) nickname, domain, debug, None, emoji_content)
if debug: if debug:
print('DEBUG: post reaction via c2s - ' + post_filename) print('DEBUG: post reaction via c2s - ' + post_filename)
@ -449,8 +452,9 @@ def outbox_undo_reaction(recent_posts_cache: {},
print('DEBUG: c2s undo reaction post not found in inbox or outbox') print('DEBUG: c2s undo reaction post not found in inbox or outbox')
print(message_id) print(message_id)
return True return True
actor_url = get_actor_from_post(message_json)
undo_reaction_collection_entry(recent_posts_cache, base_dir, post_filename, undo_reaction_collection_entry(recent_posts_cache, base_dir, post_filename,
message_id, message_json['actor'], message_id, actor_url,
domain, debug, None, emoji_content) domain, debug, None, emoji_content)
if debug: if debug:
print('DEBUG: post undo reaction via c2s - ' + post_filename) print('DEBUG: post undo reaction via c2s - ' + post_filename)
@ -642,7 +646,8 @@ def html_emoji_reactions(post_json_object: {}, interactive: bool,
base_url = actor + '?react=' + react_by base_url = actor + '?react=' + react_by
else: else:
base_url = actor + '?unreact=' + react_by base_url = actor + '?unreact=' + react_by
base_url += '?actor=' + post_json_object['actor'] actor_url = get_actor_from_post(post_json_object)
base_url += '?actor=' + actor_url
base_url += '?tl=' + box_name base_url += '?tl=' + box_name
base_url += '?page=' + str(page_number) base_url += '?page=' + str(page_number)
base_url += '?emojreact=' base_url += '?emojreact='

View File

@ -45,6 +45,7 @@ from utils import is_float
from utils import get_category_types from utils import get_category_types
from utils import get_shares_files_list from utils import get_shares_files_list
from utils import local_actor_url from utils import local_actor_url
from utils import get_actor_from_post
from media import process_meta_data from media import process_meta_data
from media import convert_image_to_low_bandwidth from media import convert_image_to_low_bandwidth
from filters import is_filtered_globally from filters import is_filtered_globally
@ -2088,6 +2089,7 @@ def vf_proposal_from_share(shared_item: {},
"http://www.ontology-of-units-of-measure.org/resource/om-2/" "http://www.ontology-of-units-of-measure.org/resource/om-2/"
share_id = _vf_share_id(shared_item['shareId']) share_id = _vf_share_id(shared_item['shareId'])
published = date_seconds_to_string(shared_item['published']) published = date_seconds_to_string(shared_item['published'])
actor_url = get_actor_from_post(shared_item)
offer_item = { offer_item = {
"@context": [ "@context": [
"https://www.w3.org/ns/activitystreams", "https://www.w3.org/ns/activitystreams",
@ -2111,7 +2113,7 @@ def vf_proposal_from_share(shared_item: {},
], ],
"type": share_type, "type": share_type,
"id": share_id, "id": share_id,
"attributedTo": shared_item['actor'], "attributedTo": actor_url,
"name": shared_item['displayName'], "name": shared_item['displayName'],
"content": shared_item['summary'], "content": shared_item['summary'],
"published": published, "published": published,
@ -2123,7 +2125,7 @@ def vf_proposal_from_share(shared_item: {},
"hasUnit": "one", "hasUnit": "one",
"hasNumericalValue": str(shared_item['itemQty']) "hasNumericalValue": str(shared_item['itemQty'])
}, },
publishes_direction: shared_item['actor'] publishes_direction: actor_url
}, },
"attachment": [], "attachment": [],
"unitBased": False, "unitBased": False,
@ -2176,7 +2178,7 @@ def vf_proposal_from_share(shared_item: {},
"hasUnit": "one", "hasUnit": "one",
"hasNumericalValue": str(shared_item['itemPrice']) "hasNumericalValue": str(shared_item['itemPrice'])
}, },
reciprocal_direction: shared_item['actor'] reciprocal_direction: actor_url
} }
return offer_item return offer_item

View File

@ -22,6 +22,7 @@ from utils import set_occupation_skills_list
from utils import acct_dir from utils import acct_dir
from utils import local_actor_url from utils import local_actor_url
from utils import has_actor from utils import has_actor
from utils import get_actor_from_post
def set_skills_from_dict(actor_json: {}, skills_dict: {}) -> []: def set_skills_from_dict(actor_json: {}, skills_dict: {}) -> []:
@ -157,12 +158,13 @@ def outbox_skills(base_dir: str, nickname: str, message_json: {},
if not has_object_string(message_json, debug): if not has_object_string(message_json, debug):
return False return False
actor_nickname = get_nickname_from_actor(message_json['actor']) actor_url = get_actor_from_post(message_json)
actor_nickname = get_nickname_from_actor(actor_url)
if not actor_nickname: if not actor_nickname:
return False return False
if actor_nickname != nickname: if actor_nickname != nickname:
return False return False
domain, _ = get_domain_from_actor(message_json['actor']) domain, _ = get_domain_from_actor(actor_url)
skill = message_json['object'].replace('"', '').split(';')[0].strip() skill = message_json['object'].replace('"', '').split(';')[0].strip()
skill_level_percent_str = \ skill_level_percent_str = \
message_json['object'].replace('"', '').split(';')[1].strip() message_json['object'].replace('"', '').split(';')[1].strip()

View File

@ -27,6 +27,7 @@ from utils import is_pgp_encrypted
from utils import has_object_dict from utils import has_object_dict
from utils import acct_dir from utils import acct_dir
from utils import local_actor_url from utils import local_actor_url
from utils import get_actor_from_post
from content import html_replace_quote_marks from content import html_replace_quote_marks
SPEAKER_REMOVE_CHARS = ('.\n', '. ', ',', ';', '?', '!') SPEAKER_REMOVE_CHARS = ('.\n', '. ', ',', ';', '?', '!')
@ -492,14 +493,16 @@ def _post_to_speaker_json(base_dir: str, http_prefix: str,
urllib.parse.unquote_plus(post_json_object_summary) urllib.parse.unquote_plus(post_json_object_summary)
summary = html.unescape(summary) summary = html.unescape(summary)
actor_url = get_actor_from_post(post_json_object)
speaker_name = \ speaker_name = \
get_display_name(base_dir, post_json_object['actor'], person_cache) get_display_name(base_dir, actor_url, person_cache)
if not speaker_name: if not speaker_name:
return return
speaker_name = _remove_emoji_from_text(speaker_name) speaker_name = _remove_emoji_from_text(speaker_name)
speaker_name = speaker_name.replace('_', ' ') speaker_name = speaker_name.replace('_', ' ')
speaker_name = camel_case_split(speaker_name) speaker_name = camel_case_split(speaker_name)
gender = get_gender_from_bio(base_dir, post_json_object['actor'], actor_url = get_actor_from_post(post_json_object)
gender = get_gender_from_bio(base_dir, actor_url,
person_cache, translate) person_cache, translate)
if announcing_actor: if announcing_actor:
announced_nickname = get_nickname_from_actor(announcing_actor) announced_nickname = get_nickname_from_actor(announcing_actor)

View File

@ -4013,7 +4013,8 @@ def has_actor(post_json_object: {}, debug: bool) -> bool:
"""Does the given post have an actor? """Does the given post have an actor?
""" """
if post_json_object.get('actor'): if post_json_object.get('actor'):
if '#' in post_json_object['actor']: actor_url = get_actor_from_post(post_json_object)
if '#' in actor_url or not actor_url:
return False return False
return True return True
if debug: if debug:
@ -4881,3 +4882,17 @@ def is_valid_date(date_str: str) -> bool:
return False return False
date_sect_ctr += 1 date_sect_ctr += 1
return True return True
def get_actor_from_post(post_json_object: {}) -> str:
"""Gets the actor url from the given post
"""
if not post_json_object.get('actor'):
return ''
if isinstance(post_json_object['actor'], str):
return post_json_object['actor']
if isinstance(post_json_object['actor'], dict):
if post_json_object['actor'].get('id'):
if isinstance(post_json_object['actor']['id'], str):
return post_json_object['actor']['id']
return ''

View File

@ -15,6 +15,7 @@ from utils import get_display_name
from utils import get_nickname_from_actor from utils import get_nickname_from_actor
from utils import has_object_dict from utils import has_object_dict
from utils import load_json from utils import load_json
from utils import get_actor_from_post
from person import get_person_avatar_url from person import get_person_avatar_url
from webapp_utils import html_header_with_external_style from webapp_utils import html_header_with_external_style
from webapp_utils import html_footer from webapp_utils import html_footer
@ -139,7 +140,8 @@ def html_likers_of_post(base_dir: str, nickname: str,
for like_item in obj[dict_name]['items']: for like_item in obj[dict_name]['items']:
if not like_item.get('actor'): if not like_item.get('actor'):
continue continue
liker_actor = like_item['actor'] actor_url = get_actor_from_post(like_item)
liker_actor = actor_url
liker_display_name = \ liker_display_name = \
get_display_name(base_dir, liker_actor, person_cache) get_display_name(base_dir, liker_actor, person_cache)
if liker_display_name: if liker_display_name:

View File

@ -74,6 +74,7 @@ from utils import is_unlisted_post
from utils import language_right_to_left from utils import language_right_to_left
from utils import get_attributed_to from utils import get_attributed_to
from utils import get_reply_to from utils import get_reply_to
from utils import get_actor_from_post
from content import format_mixed_right_to_left from content import format_mixed_right_to_left
from content import replace_remote_hashtags from content import replace_remote_hashtags
from content import detect_dogwhistles from content import detect_dogwhistles
@ -615,17 +616,19 @@ def _get_reply_icon_html(base_dir: str, nickname: str, domain: str,
if conversation_id: if conversation_id:
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)
reply_str += \ reply_str += \
' <a class="imageAnchor" href="/users/' + \ ' <a class="imageAnchor" href="/users/' + \
nickname + '?replyto=' + reply_to_link + \ nickname + '?replyto=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
conversation_str + \ conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n' '" title="' + reply_to_this_post_str + '" tabindex="10">\n'
elif is_unlisted_reply: elif is_unlisted_reply:
actor_url = get_actor_from_post(post_json_object)
reply_str += \ reply_str += \
' <a class="imageAnchor" href="/users/' + \ ' <a class="imageAnchor" href="/users/' + \
nickname + '?replyunlisted=' + reply_to_link + \ nickname + '?replyunlisted=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
conversation_str + \ conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n' '" title="' + reply_to_this_post_str + '" tabindex="10">\n'
else: else:
@ -633,19 +636,21 @@ def _get_reply_icon_html(base_dir: str, nickname: str, domain: str,
reply_type = 'replydm' reply_type = 'replydm'
if is_chat_message(post_json_object): if is_chat_message(post_json_object):
reply_type = 'replychat' reply_type = 'replychat'
actor_url = get_actor_from_post(post_json_object)
reply_str += \ reply_str += \
' ' + \ ' ' + \
'<a class="imageAnchor" href="/users/' + nickname + \ '<a class="imageAnchor" href="/users/' + nickname + \
'?' + reply_type + '=' + reply_to_link + \ '?' + reply_type + '=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
conversation_str + \ conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n' '" title="' + reply_to_this_post_str + '" tabindex="10">\n'
else: else:
actor_url = get_actor_from_post(post_json_object)
reply_str += \ reply_str += \
' ' + \ ' ' + \
'<a class="imageAnchor" href="/users/' + nickname + \ '<a class="imageAnchor" href="/users/' + nickname + \
'?replyfollowers=' + reply_to_link + \ '?replyfollowers=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
conversation_str + \ conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n' '" title="' + reply_to_this_post_str + '" tabindex="10">\n'
@ -664,7 +669,7 @@ def _get_edit_icon_html(base_dir: str, nickname: str, domain_full: str,
"""Returns html for the edit icon/button """Returns html for the edit icon/button
""" """
edit_str = '' edit_str = ''
actor = post_json_object['actor'] actor = get_actor_from_post(post_json_object)
# This should either be a post which you created, # This should either be a post which you created,
# or it could be generated from the newswire (see # or it could be generated from the newswire (see
# _add_blogs_to_newswire) in which case anyone with # _add_blogs_to_newswire) in which case anyone with
@ -892,10 +897,11 @@ def _get_announce_icon_html(is_announced: bool,
announce_link_str = '?' + \ announce_link_str = '?' + \
announce_link + '=' + announce_post_id + page_number_param announce_link + '=' + announce_post_id + page_number_param
actor_url = get_actor_from_post(post_json_object)
announce_str += \ announce_str += \
' <a class="imageAnchor" href="/users/' + \ ' <a class="imageAnchor" href="/users/' + \
nickname + announce_link_str + unannounce_link_str + \ nickname + announce_link_str + unannounce_link_str + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
'?bm=' + timeline_post_bookmark + first_post_str + \ '?bm=' + timeline_post_bookmark + first_post_str + \
'?tl=' + box_name + '" title="' + announce_title + '" tabindex="10">\n' '?tl=' + box_name + '" title="' + announce_title + '" tabindex="10">\n'
@ -976,11 +982,12 @@ def _get_like_icon_html(nickname: str, domain_full: str,
if first_post_id: if first_post_id:
first_post_str = '?firstpost=' + first_post_id.replace('#', '/') first_post_str = '?firstpost=' + first_post_id.replace('#', '/')
actor_url = get_actor_from_post(post_json_object)
like_str += \ like_str += \
' <a class="imageAnchor" href="/users/' + nickname + '?' + \ ' <a class="imageAnchor" href="/users/' + nickname + '?' + \
like_link + '=' + like_post_id + \ like_link + '=' + like_post_id + \
page_number_param + \ page_number_param + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
'?bm=' + timeline_post_bookmark + first_post_str + \ '?bm=' + timeline_post_bookmark + first_post_str + \
'?tl=' + box_name + '" title="' + like_title + like_count_str + \ '?tl=' + box_name + '" title="' + like_title + like_count_str + \
'" tabindex="10">\n' '" tabindex="10">\n'
@ -1037,11 +1044,12 @@ def _get_bookmark_icon_html(base_dir: str,
if first_post_id: if first_post_id:
first_post_str = '?firstpost=' + first_post_id.replace('#', '/') first_post_str = '?firstpost=' + first_post_id.replace('#', '/')
actor_url = get_actor_from_post(post_json_object)
bookmark_str = \ bookmark_str = \
' <a class="imageAnchor" href="/users/' + nickname + '?' + \ ' <a class="imageAnchor" href="/users/' + nickname + '?' + \
bookmark_link + '=' + bookmark_post_id + \ bookmark_link + '=' + bookmark_post_id + \
page_number_param + \ page_number_param + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
'?bm=' + timeline_post_bookmark + first_post_str + \ '?bm=' + timeline_post_bookmark + first_post_str + \
'?tl=' + box_name + '" title="' + bookmark_title + \ '?tl=' + box_name + '" title="' + bookmark_title + \
'" tabindex="10">\n' '" tabindex="10">\n'
@ -1083,10 +1091,11 @@ def _get_reaction_icon_html(nickname: str, post_json_object: {},
if first_post_id: if first_post_id:
first_post_str = '?firstpost=' + first_post_id.replace('#', '/') first_post_str = '?firstpost=' + first_post_id.replace('#', '/')
actor_url = get_actor_from_post(post_json_object)
reaction_str = \ reaction_str = \
' <a class="imageAnchor" href="/users/' + nickname + \ ' <a class="imageAnchor" href="/users/' + nickname + \
'?selreact=' + reaction_post_id + page_number_param + \ '?selreact=' + reaction_post_id + page_number_param + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
'?bm=' + timeline_post_reaction + first_post_str + \ '?bm=' + timeline_post_reaction + first_post_str + \
'?tl=' + box_name + '" title="' + reaction_title + \ '?tl=' + box_name + '" title="' + reaction_title + \
'" tabindex="10">\n' '" tabindex="10">\n'
@ -2086,7 +2095,7 @@ def individual_post_as_html(signing_priv_key_pem: str,
# benchmark # benchmark
post_start_time = time.time() post_start_time = time.time()
post_actor = post_json_object['actor'] post_actor = get_actor_from_post(post_json_object)
# ZZZzzz # ZZZzzz
if is_person_snoozed(base_dir, nickname, domain, post_actor): if is_person_snoozed(base_dir, nickname, domain, post_actor):
@ -2309,10 +2318,11 @@ def individual_post_as_html(signing_priv_key_pem: str,
if is_recent_post(post_json_object, 3): if is_recent_post(post_json_object, 3):
if post_json_object.get('actor'): if post_json_object.get('actor'):
if not os.path.isfile(announce_filename + '.tts'): if not os.path.isfile(announce_filename + '.tts'):
actor_url = get_actor_from_post(post_json_object)
update_speaker(base_dir, http_prefix, update_speaker(base_dir, http_prefix,
nickname, domain, domain_full, nickname, domain, domain_full,
post_json_object, person_cache, post_json_object, person_cache,
translate, post_json_object['actor'], translate, actor_url,
theme_name, system_language, theme_name, system_language,
box_name) box_name)
try: try:
@ -3303,13 +3313,14 @@ def html_emoji_reaction_picker(recent_posts_cache: {}, max_recent_posts: int,
emoji_picks_str = '' emoji_picks_str = ''
base_url = '/users/' + nickname base_url = '/users/' + nickname
post_id = remove_id_ending(post_json_object['id']) post_id = remove_id_ending(post_json_object['id'])
actor_url = get_actor_from_post(post_json_object)
for _, item in reactions_json.items(): for _, item in reactions_json.items():
emoji_picks_str += '<div class="container">\n' emoji_picks_str += '<div class="container">\n'
for emoji_content in item: for emoji_content in item:
emoji_content_encoded = urllib.parse.quote_plus(emoji_content) emoji_content_encoded = urllib.parse.quote_plus(emoji_content)
emoji_url = \ emoji_url = \
base_url + '?react=' + post_id + \ base_url + '?react=' + post_id + \
'?actor=' + post_json_object['actor'] + \ '?actor=' + actor_url + \
'?tl=' + box_name + \ '?tl=' + box_name + \
'?page=' + str(page_number) + \ '?page=' + str(page_number) + \
'?emojreact=' + emoji_content_encoded '?emojreact=' + emoji_content_encoded

View File

@ -39,6 +39,7 @@ from utils import get_reply_interval_hours
from utils import get_account_timezone from utils import get_account_timezone
from utils import remove_eol from utils import remove_eol
from utils import is_valid_date from utils import is_valid_date
from utils import get_actor_from_post
from languages import get_actor_languages from languages import get_actor_languages
from skills import get_skills from skills import get_skills
from theme import get_themes_list from theme import get_themes_list
@ -167,8 +168,9 @@ def _valid_profile_preview_post(post_json_object: {},
return False, None return False, None
# convert actor back to id # convert actor back to id
if isinstance(post_json_object['actor'], dict): if isinstance(post_json_object['actor'], dict):
if post_json_object['actor'].get('id'): actor_url = get_actor_from_post(post_json_object)
post_json_object['actor'] = post_json_object['actor']['id'] if actor_url:
post_json_object['actor'] = actor_url
if has_object_dict(post_json_object): if has_object_dict(post_json_object):
# convert attributedTo actor back to id # convert attributedTo actor back to id
if post_json_object['object'].get('attributedTo'): if post_json_object['object'].get('attributedTo'):
@ -178,7 +180,8 @@ def _valid_profile_preview_post(post_json_object: {},
post_json_object['object']['attributedTo'] = \ post_json_object['object']['attributedTo'] = \
post_json_object['object']['attributedTo']['id'] post_json_object['object']['attributedTo']['id']
if not is_announced_feed_item: if not is_announced_feed_item:
if post_json_object['actor'] != person_url and \ actor_url = get_actor_from_post(post_json_object)
if actor_url != person_url and \
post_json_object['object']['type'] != 'Page': post_json_object['object']['type'] != 'Page':
return False, None return False, None
return True, post_json_object return True, post_json_object

View File

@ -20,6 +20,7 @@ from utils import acct_dir
from utils import is_float from utils import is_float
from utils import local_actor_url from utils import local_actor_url
from utils import remove_eol from utils import remove_eol
from utils import get_actor_from_post
from follow import follower_approval_active from follow import follower_approval_active
from person import is_person_snoozed from person import is_person_snoozed
from markdown import markdown_to_html from markdown import markdown_to_html
@ -1188,7 +1189,7 @@ def html_individual_share(domain: str, share_id: str,
contact_title_str = translate['Request to stay'] contact_title_str = translate['Request to stay']
button_style_str = 'contactbutton' button_style_str = 'contactbutton'
contact_actor = shared_item['actor'] contact_actor = get_actor_from_post(shared_item)
profile_str += \ profile_str += \
'<p>' + \ '<p>' + \
'<a href="' + actor + \ '<a href="' + actor + \
@ -1263,11 +1264,12 @@ def _html_shares_timeline(translate: {}, page_number: int, items_per_page: int,
for _, shared_item in shares_json.items(): for _, shared_item in shares_json.items():
show_contact_button = False show_contact_button = False
if shared_item['actor'] != actor: actor_url = get_actor_from_post(shared_item)
if actor_url != actor:
show_contact_button = True show_contact_button = True
show_remove_button = False show_remove_button = False
if '___' + domain in shared_item['shareId']: if '___' + domain in shared_item['shareId']:
if shared_item['actor'] == actor or \ if actor_url == actor or \
is_admin_account or is_moderator_account: is_admin_account or is_moderator_account:
show_remove_button = True show_remove_button = True
timeline_str += \ timeline_str += \