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 has_actor
from utils import has_object_string_type
from utils import get_actor_from_post
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'):
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
domain = get_full_domain(domain, port)
@ -101,7 +103,7 @@ def _accept_follow(base_dir: str, message_json: {},
return
if debug:
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)
if not nickname:
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
if not has_actor(message_json, debug):
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:
print('DEBUG: "users" or "profile" missing from actor in ' +
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 debug:
print('DEBUG: ' + message_json['type'] +
' from domain not permitted - ' + domain)
return False
nickname = get_nickname_from_actor(message_json['actor'])
nickname = get_nickname_from_actor(actor_url)
if not nickname:
# single user instance
nickname = 'dev'

View File

@ -27,6 +27,7 @@ from utils import local_actor_url
from utils import replace_users_with_at
from utils import has_actor
from utils import has_object_string_type
from utils import get_actor_from_post
from posts import send_signed_json
from posts import get_person_box
from session import post_json
@ -61,11 +62,12 @@ def is_self_announce(post_json_object: {}) -> bool:
return False
if not post_json_object.get('object'):
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
if not isinstance(post_json_object['object'], str):
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: {},
@ -86,20 +88,21 @@ def outbox_announce(recent_posts_cache: {},
return False
if is_self_announce(message_json):
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:
print('WARN: no nickname found in ' + message_json['actor'])
print('WARN: no nickname found in ' + actor_url)
return False
domain, _ = get_domain_from_actor(message_json['actor'])
domain, _ = get_domain_from_actor(actor_url)
if not domain:
print('WARN: no domain found in ' + message_json['actor'])
print('WARN: no domain found in ' + actor_url)
return False
post_filename = locate_post(base_dir, nickname, domain,
message_json['object'])
if post_filename:
update_announce_collection(recent_posts_cache,
base_dir, post_filename,
message_json['actor'],
actor_url,
nickname, domain, debug)
return True
elif message_json['type'] == 'Undo':
@ -108,20 +111,21 @@ def outbox_announce(recent_posts_cache: {},
if message_json['object']['type'] == 'Announce':
if not isinstance(message_json['object']['object'], str):
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:
print('WARN: no nickname found in ' + message_json['actor'])
print('WARN: no nickname found in ' + actor_url)
return False
domain, _ = get_domain_from_actor(message_json['actor'])
domain, _ = get_domain_from_actor(actor_url)
if not domain:
print('WARN: no domain found in ' + message_json['actor'])
print('WARN: no domain found in ' + actor_url)
return False
post_filename = locate_post(base_dir, nickname, domain,
message_json['object']['object'])
if post_filename:
undo_announce_collection_entry(recent_posts_cache,
base_dir, post_filename,
message_json['actor'],
actor_url,
domain, debug)
return True
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(message_id)
return True
actor_url = get_actor_from_post(message_json)
undo_announce_collection_entry(recent_posts_cache, base_dir, post_filename,
message_json['actor'], domain, debug)
actor_url, domain, debug)
if debug:
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 local_actor_url
from utils import has_actor
from utils import get_actor_from_post
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):
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:
return False
if actor_nickname != nickname:
return False
domain, _ = get_domain_from_actor(message_json['actor'])
domain, _ = get_domain_from_actor(actor_url)
if not domain:
return False
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 has_actor
from utils import text_in_file
from utils import get_actor_from_post
from conversation import mute_conversation
from conversation import unmute_conversation
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):
return
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
if not message_json['type'] == 'Ignore':
return
@ -1413,7 +1415,8 @@ def outbox_undo_mute(base_dir: str, http_prefix: str,
if not has_actor(message_json, debug):
return
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
if not message_json['type'] == 'Undo':
return

View File

@ -32,6 +32,7 @@ from utils import has_object_string_type
from utils import text_in_file
from utils import remove_eol
from utils import remove_html
from utils import get_actor_from_post
from posts import get_person_box
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(message_url)
return True
actor_url = get_actor_from_post(message_json)
update_bookmarks_collection(recent_posts_cache,
base_dir, post_filename, message_url,
message_json['actor'], domain, debug)
actor_url, domain, debug)
if debug:
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(message_url)
return True
actor_url = get_actor_from_post(message_json)
update_bookmarks_collection(recent_posts_cache,
base_dir, post_filename, message_url,
message_json['actor'], domain, debug)
actor_url, domain, debug)
if debug:
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 has_group_type
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_approve_follow_request_thread
from announce import create_announce
@ -2178,9 +2179,10 @@ class PubServer(BaseHTTPRequestHandler):
# actor should be a string
if debug:
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: ' +
'actor should be a string ' + str(message_json['actor']))
'actor should be a string ' + str(actor_url))
self._400()
self.server.postreq_busy = False
return 3
@ -2262,8 +2264,9 @@ class PubServer(BaseHTTPRequestHandler):
if message_json['object'].get('content'):
content_str = message_json['object']['content']
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 ' +
message_json['actor'])
actor_url)
self._400()
self.server.postreq_busy = False
return 3
@ -2274,23 +2277,26 @@ class PubServer(BaseHTTPRequestHandler):
message_json['object']['type'] != 'Application' and \
message_json['object']['type'] != 'Group':
if len(message_json['object']['summary']) > 1024:
actor_url = get_actor_from_post(message_json)
print('INBOX: summary is too long ' +
message_json['actor'] + ' ' +
actor_url + ' ' +
message_json['object']['summary'])
self._400()
self.server.postreq_busy = False
return 3
if '://' in message_json['object']['summary']:
actor_url = get_actor_from_post(message_json)
print('INBOX: summary should not contain links ' +
message_json['actor'] + ' ' +
actor_url + ' ' +
message_json['object']['summary'])
self._400()
self.server.postreq_busy = False
return 3
else:
if len(message_json['object']['summary']) > 4096:
actor_url = get_actor_from_post(message_json)
print('INBOX: person summary is too long ' +
message_json['actor'] + ' ' +
actor_url + ' ' +
message_json['object']['summary'])
self._400()
self.server.postreq_busy = False
@ -2335,10 +2341,11 @@ class PubServer(BaseHTTPRequestHandler):
# actor should look like a url
if debug:
print('INBOX: checking that actor looks like a url')
if '://' not in message_json['actor'] or \
'.' not in message_json['actor']:
actor_url = get_actor_from_post(message_json)
if '://' not in actor_url or \
'.' not in actor_url:
print('INBOX: POST actor does not look like a url ' +
message_json['actor'])
actor_url)
self._400()
self.server.postreq_busy = False
return 3
@ -2348,18 +2355,19 @@ class PubServer(BaseHTTPRequestHandler):
print('INBOX: checking for local network access')
if not self.server.allow_local_network_access:
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:
if local_network_pattern in message_json['actor']:
if local_network_pattern in actor_url:
print('INBOX: POST actor contains local network address ' +
message_json['actor'])
actor_url)
self._400()
self.server.postreq_busy = False
return 3
message_domain, _ = \
get_domain_from_actor(message_json['actor'])
actor_url = get_actor_from_post(message_json)
message_domain, _ = get_domain_from_actor(actor_url)
if not message_domain:
print('INBOX: POST from unknown domain ' + message_json['actor'])
print('INBOX: POST from unknown domain ' + actor_url)
self._400()
self.server.postreq_busy = False
return 3
@ -2379,10 +2387,9 @@ class PubServer(BaseHTTPRequestHandler):
self.server.postreq_busy = False
return 3
message_nickname = \
get_nickname_from_actor(message_json['actor'])
message_nickname = get_nickname_from_actor(actor_url)
if not message_nickname:
print('INBOX: POST from unknown nickname ' + message_json['actor'])
print('INBOX: POST from unknown nickname ' + actor_url)
self._400()
self.server.postreq_busy = False
return 3
@ -2402,7 +2409,7 @@ class PubServer(BaseHTTPRequestHandler):
if message_domain:
print('INBOX: Queue: ' +
'Inbox queue is full. Incoming post from ' +
message_json['actor'])
actor_url)
else:
print('INBOX: Queue: Inbox queue is full')
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 date_utcnow
from utils import date_epoch
from utils import get_actor_from_post
from session import post_json
from webfinger import webfinger_handle
from auth import create_basic_auth_header
@ -138,9 +139,10 @@ def outbox_delete(base_dir: str, http_prefix: str,
if debug:
print('DEBUG: c2s delete request arrived in outbox')
delete_prefix = http_prefix + '://' + domain
actor_url = get_actor_from_post(message_json)
if (not allow_deletion and
(not message_json['object'].startswith(delete_prefix) or
not message_json['actor'].startswith(delete_prefix))):
not actor_url.startswith(delete_prefix))):
if debug:
print('DEBUG: delete not permitted from other instances')
return

View File

@ -34,6 +34,7 @@ from utils import get_domain_from_actor
from utils import is_pgp_encrypted
from utils import local_actor_url
from utils import get_reply_to
from utils import get_actor_from_post
from session import create_session
from speaker import speakable_text
from speaker import get_speaker_pitch
@ -801,7 +802,7 @@ def _read_local_box_post(session, nickname: str, domain: str,
print('')
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)
recent_posts_cache = {}
allow_local_network_access = False
@ -1142,7 +1143,8 @@ def _desktop_show_box(indent: str,
if post_json_object.get('actor') and \
post_json_object.get('object'):
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 = _pad_to_width(name, name_width)
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 text_in_file
from utils import remove_eol
from utils import get_actor_from_post
from acceptreject import create_accept
from acceptreject import create_reject
from webfinger import webfinger_handle
@ -803,7 +804,8 @@ def followed_account_accepts(session, base_dir: str, http_prefix: str,
group_account = False
if follow_json:
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
extra_headers = {}
@ -858,7 +860,7 @@ def followed_account_rejects(session, session_onion, session_i2p,
follow_activity_filename)
return None
# actor who made the follow request
person_url = follow_json['actor']
person_url = get_actor_from_post(follow_json)
# create the reject activity
reject_json = \
@ -1474,17 +1476,15 @@ def outbox_undo_follow(base_dir: str, message_json: {}, debug: bool) -> None:
if debug:
print('DEBUG: undo follow arrived in outbox')
nickname_follower = \
get_nickname_from_actor(message_json['object']['actor'])
actor_url = get_actor_from_post(message_json['object'])
nickname_follower = get_nickname_from_actor(actor_url)
if not nickname_follower:
print('WARN: unable to find nickname in ' +
message_json['object']['actor'])
actor_url)
return
domain_follower, port_follower = \
get_domain_from_actor(message_json['object']['actor'])
domain_follower, port_follower = get_domain_from_actor(actor_url)
if not domain_follower:
print('WARN: unable to find domain in ' +
message_json['object']['actor'])
print('WARN: unable to find domain in ' + actor_url)
return
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 get_attributed_to
from utils import get_reply_to
from utils import get_actor_from_post
from categories import get_hashtag_categories
from categories import set_hashtag_category
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
post_id = remove_id_ending(post_json_object['object']['id'])
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'])
if not actor:
return
@ -573,15 +574,16 @@ def inbox_message_has_params(message_json: {}) -> bool:
return False
# 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: ' +
str(message_json['actor']))
actor_url)
pprint(message_json)
return False
# type should be a string
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: ' +
str(message_json['type']))
return False
@ -589,7 +591,7 @@ def inbox_message_has_params(message_json: {}) -> bool:
# object should be a dict or a string
if not has_object_dict(message_json):
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: ' +
str(message_json['object']))
return False
@ -611,7 +613,7 @@ def inbox_permitted_message(domain: str, message_json: {},
if not has_actor(message_json, False):
return False
actor = message_json['actor']
actor = get_actor_from_post(message_json)
# always allow the local domain
if domain in actor:
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'])
if not sending_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
if sending_actor:
@ -948,7 +950,7 @@ def _inbox_post_recipients(base_dir: str, post_json_object: {},
domain = get_full_domain(domain, port)
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
follower_recipients = False
@ -1062,13 +1064,13 @@ def _receive_undo_follow(base_dir: str, message_json: {},
if debug:
print('DEBUG: undo follow request has no actor within object')
return False
actor = message_json['object']['actor']
actor = get_actor_from_post(message_json['object'])
if not has_users_path(actor):
if debug:
print('DEBUG: undo follow request "users" or "profile" missing ' +
'from actor within object')
return False
if actor != message_json['actor']:
if actor != get_actor_from_post(message_json):
if debug:
print('DEBUG: undo follow request actors do not match')
return False
@ -1146,7 +1148,8 @@ def _receive_undo(base_dir: str, message_json: {}, debug: bool,
print('DEBUG: Undo activity received')
if not has_actor(message_json, debug):
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:
print('DEBUG: "users" or "profile" missing from actor')
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):
return False
# 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
save_json(message_json, post_filename)
# 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']:
return False
# 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 ' +
post_json_object['actor'] + ' != ' + message_json['actor'])
actor_url + ' != ' + actor_url2)
return False
# has the content changed?
if post_json_object['object']['content'] == \
@ -1755,13 +1762,14 @@ def _receive_move_activity(session, base_dir: str,
str(message_json['target']))
return False
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 ' +
message_json['actor'] + ' moving to ' + message_json['target'])
previous_actor = message_json['actor']
elif message_json['target'] == message_json['actor']:
actor_url + ' moving to ' + message_json['target'])
previous_actor = actor_url
elif message_json['target'] == actor_url:
print('INBOX: Move activity sent by new actor ' +
message_json['actor'] + ' moving from ' +
actor_url + ' moving from ' +
message_json['object'])
previous_actor = message_json['object']
if not previous_actor:
@ -1846,7 +1854,8 @@ def _receive_update_activity(recent_posts_cache: {}, session, base_dir: str,
return False
if not has_object_string_type(message_json, debug):
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:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'])
@ -1895,9 +1904,10 @@ def _receive_update_activity(recent_posts_cache: {}, session, base_dir: str,
message_json['object'].get('id'):
if debug:
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 = \
get_domain_from_actor(message_json['actor'])
get_domain_from_actor(actor_url)
if update_nickname and update_domain:
if _person_receive_update(base_dir,
domain, port,
@ -1945,7 +1955,8 @@ def _receive_like(recent_posts_cache: {},
if debug:
print('DEBUG: ' + message_json['type'] + ' has no "to" list')
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:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'])
@ -1972,7 +1983,7 @@ def _receive_like(recent_posts_cache: {},
if debug:
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_dom = handle.split('@')[1]
if not _already_liked(base_dir,
@ -2081,7 +2092,8 @@ def _receive_undo_like(recent_posts_cache: {},
return False
if not has_object_string_object(message_json, debug):
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:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + ' like')
@ -2107,7 +2119,7 @@ def _receive_undo_like(recent_posts_cache: {},
return True
if debug:
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']
undo_likes_collection_entry(recent_posts_cache, base_dir, post_filename,
post_liked_id, like_actor, domain, debug, None)
@ -2213,11 +2225,12 @@ def _receive_reaction(recent_posts_cache: {},
if debug:
print('DEBUG: ' + message_json['type'] + ' content is not string')
return False
actor_url = get_actor_from_post(message_json)
if not valid_emoji_content(message_json['content']):
print('_receive_reaction: Invalid emoji reaction: "' +
message_json['content'] + '" from ' + message_json['actor'])
message_json['content'] + '" from ' + actor_url)
return False
if not has_users_path(message_json['actor']):
if not has_users_path(actor_url):
if debug:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'])
@ -2254,7 +2267,7 @@ def _receive_reaction(recent_posts_cache: {},
if debug:
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_dom = handle.split('@')[1]
if not _already_reacted(base_dir,
@ -2394,12 +2407,13 @@ def _receive_zot_reaction(recent_posts_cache: {},
print('DEBUG: ' + message_json['object']['type'] +
' inReplyTo is not string')
return False
actor_url = get_actor_from_post(message_json)
if not valid_emoji_content(message_json['object']['content']):
print('_receive_zot_reaction: Invalid emoji reaction: "' +
message_json['object']['content'] + '" from ' +
message_json['actor'])
actor_url)
return False
if not has_users_path(message_json['actor']):
if not has_users_path(actor_url):
if debug:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['object']['type'])
@ -2437,7 +2451,7 @@ def _receive_zot_reaction(recent_posts_cache: {},
if debug:
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_dom = handle.split('@')[1]
if not _already_reacted(base_dir,
@ -2560,7 +2574,8 @@ def _receive_undo_reaction(recent_posts_cache: {},
if debug:
print('DEBUG: ' + message_json['type'] + ' content is not string')
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:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + ' reaction')
@ -2586,7 +2601,7 @@ def _receive_undo_reaction(recent_posts_cache: {},
return True
if debug:
print('DEBUG: reaction post found in inbox. Now undoing.')
reaction_actor = message_json['actor']
reaction_actor = actor_url
post_reaction_id = message_json['object']
emoji_content = remove_html(message_json['object']['content'])
if not emoji_content:
@ -2704,11 +2719,12 @@ def _receive_bookmark(recent_posts_cache: {},
return False
domain_full = get_full_domain(domain, port)
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:
print('DEBUG: inbox bookmark Add unexpected actor')
return False
if not message_json['target'].endswith(message_json['actor'] +
if not message_json['target'].endswith(actor_url +
'/tlbookmarks'):
if debug:
print('DEBUG: inbox bookmark Add target invalid ' +
@ -2741,8 +2757,7 @@ def _receive_bookmark(recent_posts_cache: {},
return True
update_bookmarks_collection(recent_posts_cache, base_dir, post_filename,
message_url2,
message_json['actor'], domain, debug)
message_url2, actor_url, domain, debug)
# regenerate the html
bookmarked_post_json = load_json(post_filename, 0, 1)
if bookmarked_post_json:
@ -2831,11 +2846,12 @@ def _receive_undo_bookmark(recent_posts_cache: {},
return False
domain_full = get_full_domain(domain, port)
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:
print('DEBUG: inbox undo bookmark Remove unexpected actor')
return False
if not message_json['target'].endswith(message_json['actor'] +
if not message_json['target'].endswith(actor_url +
'/tlbookmarks'):
if debug:
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,
post_filename,
message_json['actor'], domain, debug)
actor_url, domain, debug)
# regenerate the html
bookmarked_post_json = load_json(post_filename, 0, 1)
if bookmarked_post_json:
@ -2936,9 +2952,10 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
return False
domain_full = get_full_domain(domain, port)
delete_prefix = http_prefix + '://' + domain_full + '/'
actor_url = get_actor_from_post(message_json)
if (not allow_deletion and
(not message_json['object'].startswith(delete_prefix) or
not message_json['actor'].startswith(delete_prefix))):
not actor_url.startswith(delete_prefix))):
if debug:
print('DEBUG: delete not permitted from other instances')
return False
@ -2946,7 +2963,7 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
if debug:
print('DEBUG: ' + message_json['type'] + ' has no "to" list')
return False
if not has_users_path(message_json['actor']):
if not has_users_path(actor_url):
if debug:
print('DEBUG: ' +
'"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 ' +
message_json['type'])
return False
if message_json['actor'] not in message_json['object']:
if actor_url not in message_json['object']:
if debug:
print('DEBUG: actor is not the owner of the post to be deleted')
handle_dir = acct_handle_dir(base_dir, handle)
@ -3034,7 +3051,8 @@ def _receive_announce(recent_posts_cache: {},
if debug:
print('DEBUG: ' + message_json['type'] + ' has no "to" list')
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:
print('DEBUG: ' +
'"users" or "profile" missing from actor in ' +
@ -3069,11 +3087,11 @@ def _receive_announce(recent_posts_cache: {},
# is the announce actor blocked?
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:
print('WARN: _receive_announce no actor_nickname')
return False
actor_domain, _ = get_domain_from_actor(message_json['actor'])
actor_domain, _ = get_domain_from_actor(actor_url)
if not actor_domain:
print('WARN: _receive_announce no actor_domain')
return False
@ -3117,10 +3135,11 @@ def _receive_announce(recent_posts_cache: {},
print(message_json['object'])
return True
# 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,
message_json['actor'], nickname, domain, debug)
actor_url, nickname, domain, debug)
if debug:
print('DEBUG: Downloading announce post ' + message_json['actor'] +
print('DEBUG: Downloading announce post ' + actor_url +
' -> ' + message_json['object'])
domain_full = get_full_domain(domain, port)
@ -3215,8 +3234,9 @@ def _receive_announce(recent_posts_cache: {},
str(post_filename))
else:
if debug:
actor_url = get_actor_from_post(message_json)
print('DEBUG: Announce post downloaded for ' +
message_json['actor'] + ' -> ' + message_json['object'])
actor_url + ' -> ' + message_json['object'])
store_hash_tags(base_dir, nickname, domain,
http_prefix, domain_full,
post_json_object, translate)
@ -3309,7 +3329,8 @@ def _receive_undo_announce(recent_posts_cache: {},
return False
if message_json['object']['type'] != 'Announce':
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:
print('DEBUG: "users" or "profile" missing from actor in ' +
message_json['type'] + ' announce')
@ -3339,7 +3360,7 @@ def _receive_undo_announce(recent_posts_cache: {},
"which isn't an announcement")
return False
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):
try:
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):
return
actor = post_json_object['actor']
actor = get_actor_from_post(post_json_object)
actor_nickname = get_nickname_from_actor(actor)
if not actor_nickname:
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):
return
actor = post_json_object['actor']
actor = get_actor_from_post(post_json_object)
actor_nickname = get_nickname_from_actor(actor)
if not actor_nickname:
return
@ -4210,7 +4231,7 @@ def _is_valid_dm(base_dir: str, nickname: str, domain: str, port: int,
# who is sending a DM?
if not post_json_object.get('actor'):
return False
sending_actor = post_json_object['actor']
sending_actor = get_actor_from_post(post_json_object)
sending_actor_nickname = \
get_nickname_from_actor(sending_actor)
if not sending_actor_nickname:
@ -5573,16 +5594,17 @@ def _receive_follow_request(session, session_onion, session_i2p,
print('Receiving follow request')
if not has_actor(message_json, debug):
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:
print('DEBUG: ' +
'users/profile/author/accounts/channel missing from actor')
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 debug:
print('DEBUG: receive follow request actor without domain ' +
message_json['actor'])
actor_url)
return True
from_port = port
domain_full = get_full_domain(domain, temp_port)
@ -5592,7 +5614,7 @@ def _receive_follow_request(session, session_onion, session_i2p,
if debug:
print('DEBUG: follower from domain not permitted - ' + domain)
return True
nickname = get_nickname_from_actor(message_json['actor'])
nickname = get_nickname_from_actor(actor_url)
if not nickname:
# single user instance
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.
# Getting their public key has the same result
if debug:
print('Obtaining the following actor: ' + message_json['actor'])
print('Obtaining the following actor: ' + actor_url)
pubkey_result = \
get_person_pub_key(base_dir, curr_session,
message_json['actor'],
actor_url,
person_cache, debug, project_version,
curr_http_prefix,
this_domain, onion_domain,
@ -5734,14 +5756,14 @@ def _receive_follow_request(session, session_onion, session_i2p,
if not pubkey_result:
if debug:
print('Unable to obtain following actor: ' +
message_json['actor'])
actor_url)
elif isinstance(pubkey_result, dict):
if debug:
print('http error code trying to obtain following actor: ' +
message_json['actor'] + ' ' + str(pubkey_result))
actor_url + ' ' + str(pubkey_result))
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):
print('Group cannot follow a group')
return True
@ -5750,7 +5772,7 @@ def _receive_follow_request(session, session_onion, session_i2p,
return store_follow_request(base_dir,
nickname_to_follow, domain_to_follow, port,
nickname, domain, from_port,
message_json, debug, message_json['actor'],
message_json, debug, actor_url,
group_account)
else:
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
# /users/ path convention store the full actor
if '/users/' not in message_json['actor']:
approve_handle = message_json['actor']
if '/users/' not in actor_url:
approve_handle = actor_url
# Get the actor for the follower and add it to the cache.
# Getting their public key has the same result
if debug:
print('Obtaining the following actor: ' +
message_json['actor'])
actor_url)
pubkey_result = \
get_person_pub_key(base_dir, curr_session,
message_json['actor'],
actor_url,
person_cache, debug, project_version,
curr_http_prefix, this_domain,
onion_domain, i2p_domain,
@ -5785,11 +5807,11 @@ def _receive_follow_request(session, session_onion, session_i2p,
if not pubkey_result:
if debug:
print('Unable to obtain following actor: ' +
message_json['actor'])
actor_url)
elif isinstance(pubkey_result, dict):
if debug:
print('http error code trying to obtain ' +
'following actor: ' + message_json['actor'] +
'following actor: ' + actor_url +
' ' + str(pubkey_result))
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):
group_account = \
has_group_type(base_dir,
message_json['actor'], person_cache)
actor_url, person_cache)
if debug:
print(approve_handle + ' / ' + message_json['actor'] +
print(approve_handle + ' / ' + actor_url +
' is Group: ' + str(group_account))
if group_account and \
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,
nickname_to_follow, domain_to_follow, port,
nickname, curr_domain, curr_port,
message_json['actor'], federation_list,
actor_url, federation_list,
message_json, send_threads, post_log,
cached_webfingers, person_cache,
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 remove_post_from_cache
from utils import get_cached_post_filename
from utils import get_actor_from_post
from posts import send_signed_json
from session import post_json
from webfinger import webfinger_handle
@ -134,9 +135,10 @@ def _create_like(recent_posts_cache: {},
print('DEBUG: like object_url: ' + object_url)
return None
actor_url = get_actor_from_post(new_like_json)
update_likes_collection(recent_posts_cache,
base_dir, post_filename, object_url,
new_like_json['actor'],
actor_url,
nickname, domain, debug, None)
extra_headers = {}
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(message_id)
return True
actor_url = get_actor_from_post(message_json)
update_likes_collection(recent_posts_cache,
base_dir, post_filename, message_id,
message_json['actor'],
actor_url,
nickname, domain, debug, None)
if debug:
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(message_id)
return True
actor_url = get_actor_from_post(message_json)
undo_likes_collection_entry(recent_posts_cache, base_dir, post_filename,
message_id, message_json['actor'],
message_id, actor_url,
domain, debug, None)
if debug:
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 text_in_file
from utils import remove_eol
from utils import get_actor_from_post
from threads import thread_with_trace
from threads import begin_thread
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 ' +
handle + ' follow request from ' +
approve_nickname + '@' + approve_domain)
actor_url = get_actor_from_post(follow_json)
followed_account_accepts(curr_session, base_dir,
curr_http_prefix,
nickname,
@ -283,7 +285,7 @@ def manual_approve_follow_request(session, session_onion, session_i2p,
approve_nickname,
approve_domain,
approve_port,
follow_json['actor'],
actor_url,
federation_list,
follow_json,
send_threads, post_log,

View File

@ -34,6 +34,7 @@ from utils import acct_dir
from utils import local_actor_url
from utils import has_actor
from utils import is_quote_toot
from utils import get_actor_from_post
from blocking import is_blocked_domain
from blocking import outbox_block
from blocking import outbox_undo_block
@ -355,30 +356,31 @@ def post_message_to_outbox(session, translate: {},
return False
# 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
# actor should look like a url
if '://' not in message_json['actor'] or \
'.' not in message_json['actor']:
if '://' not in actor_url or \
'.' not in actor_url:
return False
if contains_invalid_actor_url_chars(message_json['actor']):
if contains_invalid_actor_url_chars(actor_url):
return False
# sent by an actor on a local network address?
if not allow_local_network_access:
local_network_pattern_list = get_local_network_addresses()
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
test_domain, test_port = get_domain_from_actor(message_json['actor'])
test_domain, test_port = get_domain_from_actor(actor_url)
if test_domain:
test_domain = get_full_domain(test_domain, test_port)
if is_blocked_domain(base_dir, test_domain):
if debug:
print('DEBUG: domain is blocked: ' + message_json['actor'])
print('DEBUG: domain is blocked: ' + actor_url)
return False
# replace youtube, so that google gets less tracking data
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,
system_language)
# 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'):
attachment_index = 0
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)
return False
actor_url = get_actor_from_post(message_json)
update_speaker(base_dir, http_prefix,
post_to_nickname, domain, domain_full,
message_json, person_cache,
translate, message_json['actor'],
translate, actor_url,
theme, system_language,
outbox_name)

View File

@ -71,6 +71,7 @@ from utils import local_actor_url
from utils import dangerous_svg
from utils import text_in_file
from utils import contains_statuses
from utils import get_actor_from_post
from session import get_json_valid
from session import create_session
from session import get_json
@ -1928,7 +1929,7 @@ def valid_sending_actor(session, base_dir: str,
the sending actor is valid
"""
# 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):
return False

View File

@ -87,6 +87,7 @@ from utils import dangerous_markup
from utils import acct_dir
from utils import local_actor_url
from utils import get_reply_to
from utils import get_actor_from_post
from media import get_music_metadata
from media import attach_media
from media import replace_you_tube
@ -3218,7 +3219,8 @@ def _add_followers_to_public_post(post_json_object: {}) -> None:
return
if post_json_object.get('cc'):
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):
if not post_json_object['object'].get('to'):
return
@ -3232,8 +3234,9 @@ def _add_followers_to_public_post(post_json_object: {}) -> None:
return
if post_json_object['object'].get('cc'):
return
actor_url = get_actor_from_post(post_json_object)
post_json_object['object']['cc'] = \
post_json_object['actor'] + '/followers'
actor_url + '/followers'
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 \
post_json_object['type'] == 'Remove':
if post_json_object['object']['type'] == 'Document':
post_json_object['to'] = \
[post_json_object['actor']]
post_json_object['object']['to'] = \
[post_json_object['actor']]
actor_url = get_actor_from_post(post_json_object)
post_json_object['to'] = [actor_url]
post_json_object['object']['to'] = [actor_url]
to_field_added = True
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):
return None
# 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
# get the announced post
@ -5716,24 +5719,24 @@ def download_announce(session, base_dir: str, http_prefix: str,
as_header = {
'Accept': accept_str
}
if '/channel/' in post_json_object['actor'] or \
'/accounts/' in post_json_object['actor']:
if '/channel/' in actor_url or \
'/accounts/' in actor_url:
accept_str = \
'application/ld+json; ' + \
'profile="' + profile_str + '"'
as_header = {
'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:
print('WARN: download_announce no actor_nickname')
return None
actor_domain, actor_port = \
get_domain_from_actor(post_json_object['actor'])
get_domain_from_actor(actor_url)
if not actor_domain:
print('Announce actor does not contain a ' +
'valid domain or port number: ' +
str(post_json_object['actor']))
actor_url)
return None
if is_blocked(base_dir, nickname, domain,
actor_nickname, actor_domain):
@ -6581,7 +6584,7 @@ def get_original_post_from_announce_url(announce_url: str, base_dir: str,
actor = attrib
url = orig_post_id
elif orig_post_json['object'].get('actor'):
actor = orig_post_json['actor']
actor = get_actor_from_post(orig_post_json)
url = orig_post_id
else:
# 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 dangerous_markup
from utils import get_reply_to
from utils import get_actor_from_post
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
voters_file_separator = ';;;'
voters_filename = question_post_filename.replace('.json', '.voters')
actor_url = get_actor_from_post(reply_json)
if not os.path.isfile(voters_filename):
# create a new voters file
try:
with open(voters_filename, 'w+',
encoding='utf-8') as voters_file:
voters_file.write(reply_json['actor'] +
voters_file.write(actor_url +
voters_file_separator +
reply_vote + '\n')
except OSError:
print('EX: unable to write voters file ' + voters_filename)
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
try:
with open(voters_filename, 'a+',
encoding='utf-8') as voters_file:
voters_file.write(reply_json['actor'] +
voters_file.write(actor_url +
voters_file_separator +
reply_vote + '\n')
except OSError:
@ -149,9 +151,9 @@ def question_update_votes(base_dir: str, nickname: str, domain: str,
newlines = []
save_voters_file = False
for vote_line in lines:
if vote_line.startswith(reply_json['actor'] +
if vote_line.startswith(actor_url +
voters_file_separator):
new_vote_line = reply_json['actor'] + \
new_vote_line = actor_url + \
voters_file_separator + reply_vote + '\n'
if vote_line == new_vote_line:
break

View File

@ -32,6 +32,7 @@ from utils import remove_post_from_cache
from utils import get_cached_post_filename
from utils import contains_invalid_chars
from utils import remove_eol
from utils import get_actor_from_post
from posts import send_signed_json
from session import post_json
from webfinger import webfinger_handle
@ -133,9 +134,10 @@ def _reactionpost(recent_posts_cache: {},
print('DEBUG: reaction object_url: ' + object_url)
return None
actor_url = get_actor_from_post(new_reaction_json)
update_reaction_collection(recent_posts_cache,
base_dir, post_filename, object_url,
new_reaction_json['actor'],
actor_url,
nickname, domain, debug, None,
emoji_content)
@ -408,9 +410,10 @@ def outbox_reaction(recent_posts_cache: {},
print('DEBUG: c2s reaction post not found in inbox or outbox')
print(message_id)
return True
actor_url = get_actor_from_post(message_json)
update_reaction_collection(recent_posts_cache,
base_dir, post_filename, message_id,
message_json['actor'],
actor_url,
nickname, domain, debug, None, emoji_content)
if debug:
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(message_id)
return True
actor_url = get_actor_from_post(message_json)
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)
if debug:
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
else:
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 += '?page=' + str(page_number)
base_url += '?emojreact='

View File

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

View File

@ -22,6 +22,7 @@ from utils import set_occupation_skills_list
from utils import acct_dir
from utils import local_actor_url
from utils import has_actor
from utils import get_actor_from_post
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):
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:
return False
if actor_nickname != nickname:
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_level_percent_str = \
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 acct_dir
from utils import local_actor_url
from utils import get_actor_from_post
from content import html_replace_quote_marks
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)
summary = html.unescape(summary)
actor_url = get_actor_from_post(post_json_object)
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:
return
speaker_name = _remove_emoji_from_text(speaker_name)
speaker_name = speaker_name.replace('_', ' ')
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)
if 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?
"""
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 True
if debug:
@ -4881,3 +4882,17 @@ def is_valid_date(date_str: str) -> bool:
return False
date_sect_ctr += 1
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 has_object_dict
from utils import load_json
from utils import get_actor_from_post
from person import get_person_avatar_url
from webapp_utils import html_header_with_external_style
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']:
if not like_item.get('actor'):
continue
liker_actor = like_item['actor']
actor_url = get_actor_from_post(like_item)
liker_actor = actor_url
liker_display_name = \
get_display_name(base_dir, liker_actor, person_cache)
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 get_attributed_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 replace_remote_hashtags
from content import detect_dogwhistles
@ -615,17 +616,19 @@ def _get_reply_icon_html(base_dir: str, nickname: str, domain: str,
if conversation_id:
conversation_str = '?conversationId=' + conversation_id
if is_public_reply:
actor_url = get_actor_from_post(post_json_object)
reply_str += \
' <a class="imageAnchor" href="/users/' + \
nickname + '?replyto=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n'
elif is_unlisted_reply:
actor_url = get_actor_from_post(post_json_object)
reply_str += \
' <a class="imageAnchor" href="/users/' + \
nickname + '?replyunlisted=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n'
else:
@ -633,19 +636,21 @@ def _get_reply_icon_html(base_dir: str, nickname: str, domain: str,
reply_type = 'replydm'
if is_chat_message(post_json_object):
reply_type = 'replychat'
actor_url = get_actor_from_post(post_json_object)
reply_str += \
' ' + \
'<a class="imageAnchor" href="/users/' + nickname + \
'?' + reply_type + '=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
conversation_str + \
'" title="' + reply_to_this_post_str + '" tabindex="10">\n'
else:
actor_url = get_actor_from_post(post_json_object)
reply_str += \
' ' + \
'<a class="imageAnchor" href="/users/' + nickname + \
'?replyfollowers=' + reply_to_link + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
conversation_str + \
'" 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
"""
edit_str = ''
actor = post_json_object['actor']
actor = get_actor_from_post(post_json_object)
# This should either be a post which you created,
# or it could be generated from the newswire (see
# _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 + '=' + announce_post_id + page_number_param
actor_url = get_actor_from_post(post_json_object)
announce_str += \
' <a class="imageAnchor" href="/users/' + \
nickname + announce_link_str + unannounce_link_str + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
'?bm=' + timeline_post_bookmark + first_post_str + \
'?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:
first_post_str = '?firstpost=' + first_post_id.replace('#', '/')
actor_url = get_actor_from_post(post_json_object)
like_str += \
' <a class="imageAnchor" href="/users/' + nickname + '?' + \
like_link + '=' + like_post_id + \
page_number_param + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
'?bm=' + timeline_post_bookmark + first_post_str + \
'?tl=' + box_name + '" title="' + like_title + like_count_str + \
'" tabindex="10">\n'
@ -1037,11 +1044,12 @@ def _get_bookmark_icon_html(base_dir: str,
if first_post_id:
first_post_str = '?firstpost=' + first_post_id.replace('#', '/')
actor_url = get_actor_from_post(post_json_object)
bookmark_str = \
' <a class="imageAnchor" href="/users/' + nickname + '?' + \
bookmark_link + '=' + bookmark_post_id + \
page_number_param + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
'?bm=' + timeline_post_bookmark + first_post_str + \
'?tl=' + box_name + '" title="' + bookmark_title + \
'" tabindex="10">\n'
@ -1083,10 +1091,11 @@ def _get_reaction_icon_html(nickname: str, post_json_object: {},
if first_post_id:
first_post_str = '?firstpost=' + first_post_id.replace('#', '/')
actor_url = get_actor_from_post(post_json_object)
reaction_str = \
' <a class="imageAnchor" href="/users/' + nickname + \
'?selreact=' + reaction_post_id + page_number_param + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
'?bm=' + timeline_post_reaction + first_post_str + \
'?tl=' + box_name + '" title="' + reaction_title + \
'" tabindex="10">\n'
@ -2086,7 +2095,7 @@ def individual_post_as_html(signing_priv_key_pem: str,
# benchmark
post_start_time = time.time()
post_actor = post_json_object['actor']
post_actor = get_actor_from_post(post_json_object)
# ZZZzzz
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 post_json_object.get('actor'):
if not os.path.isfile(announce_filename + '.tts'):
actor_url = get_actor_from_post(post_json_object)
update_speaker(base_dir, http_prefix,
nickname, domain, domain_full,
post_json_object, person_cache,
translate, post_json_object['actor'],
translate, actor_url,
theme_name, system_language,
box_name)
try:
@ -3303,13 +3313,14 @@ def html_emoji_reaction_picker(recent_posts_cache: {}, max_recent_posts: int,
emoji_picks_str = ''
base_url = '/users/' + nickname
post_id = remove_id_ending(post_json_object['id'])
actor_url = get_actor_from_post(post_json_object)
for _, item in reactions_json.items():
emoji_picks_str += '<div class="container">\n'
for emoji_content in item:
emoji_content_encoded = urllib.parse.quote_plus(emoji_content)
emoji_url = \
base_url + '?react=' + post_id + \
'?actor=' + post_json_object['actor'] + \
'?actor=' + actor_url + \
'?tl=' + box_name + \
'?page=' + str(page_number) + \
'?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 remove_eol
from utils import is_valid_date
from utils import get_actor_from_post
from languages import get_actor_languages
from skills import get_skills
from theme import get_themes_list
@ -167,8 +168,9 @@ def _valid_profile_preview_post(post_json_object: {},
return False, None
# convert actor back to id
if isinstance(post_json_object['actor'], dict):
if post_json_object['actor'].get('id'):
post_json_object['actor'] = post_json_object['actor']['id']
actor_url = get_actor_from_post(post_json_object)
if actor_url:
post_json_object['actor'] = actor_url
if has_object_dict(post_json_object):
# convert attributedTo actor back to id
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']['id']
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':
return False, None
return True, post_json_object

View File

@ -20,6 +20,7 @@ from utils import acct_dir
from utils import is_float
from utils import local_actor_url
from utils import remove_eol
from utils import get_actor_from_post
from follow import follower_approval_active
from person import is_person_snoozed
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']
button_style_str = 'contactbutton'
contact_actor = shared_item['actor']
contact_actor = get_actor_from_post(shared_item)
profile_str += \
'<p>' + \
'<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():
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_remove_button = False
if '___' + domain in shared_item['shareId']:
if shared_item['actor'] == actor or \
if actor_url == actor or \
is_admin_account or is_moderator_account:
show_remove_button = True
timeline_str += \