| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | __filename__ = "availability.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2022-02-03 13:58:20 +00:00
										 |  |  | __version__ = "1.3.0" | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							| 
									
										
										
										
											2021-09-10 16:14:50 +00:00
										 |  |  | __email__ = "bob@libreserver.org" | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-26 11:16:41 +00:00
										 |  |  | __module_group__ = "Profile Metadata" | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | from webfinger import webfinger_handle | 
					
						
							| 
									
										
										
										
											2021-12-28 21:36:27 +00:00
										 |  |  | from auth import create_basic_auth_header | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | from posts import get_person_box | 
					
						
							|  |  |  | from session import post_json | 
					
						
							| 
									
										
										
										
											2021-12-26 17:12:07 +00:00
										 |  |  | from utils import has_object_string | 
					
						
							| 
									
										
										
										
											2021-12-26 12:45:03 +00:00
										 |  |  | from utils import get_full_domain | 
					
						
							| 
									
										
										
										
											2021-12-27 22:19:18 +00:00
										 |  |  | from utils import get_nickname_from_actor | 
					
						
							| 
									
										
										
										
											2021-12-27 19:05:25 +00:00
										 |  |  | from utils import get_domain_from_actor | 
					
						
							| 
									
										
										
										
											2021-12-26 15:13:34 +00:00
										 |  |  | from utils import load_json | 
					
						
							| 
									
										
										
										
											2021-12-26 14:47:21 +00:00
										 |  |  | from utils import save_json | 
					
						
							| 
									
										
										
										
											2021-12-26 12:02:29 +00:00
										 |  |  | from utils import acct_dir | 
					
						
							| 
									
										
										
										
											2021-12-26 10:19:59 +00:00
										 |  |  | from utils import local_actor_url | 
					
						
							| 
									
										
										
										
											2021-12-26 17:15:04 +00:00
										 |  |  | from utils import has_actor | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def set_availability(base_dir: str, nickname: str, domain: str, | 
					
						
							|  |  |  |                      status: str) -> bool: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     """Set an availability status
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     # avoid giant strings | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  |     if len(status) > 128: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     actor_filename = acct_dir(base_dir, nickname, domain) + '.json' | 
					
						
							|  |  |  |     if not os.path.isfile(actor_filename): | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     actor_json = load_json(actor_filename) | 
					
						
							| 
									
										
										
										
											2021-12-26 10:29:52 +00:00
										 |  |  |     if actor_json: | 
					
						
							|  |  |  |         actor_json['availability'] = status | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |         save_json(actor_json, actor_filename) | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     return True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def get_availability(base_dir: str, nickname: str, domain: str) -> str: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     """Returns the availability for a given person
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     actor_filename = acct_dir(base_dir, nickname, domain) + '.json' | 
					
						
							|  |  |  |     if not os.path.isfile(actor_filename): | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     actor_json = load_json(actor_filename) | 
					
						
							| 
									
										
										
										
											2021-12-26 10:29:52 +00:00
										 |  |  |     if actor_json: | 
					
						
							|  |  |  |         if not actor_json.get('availability'): | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |             return None | 
					
						
							| 
									
										
										
										
											2021-12-26 10:29:52 +00:00
										 |  |  |         return actor_json['availability'] | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def outbox_availability(base_dir: str, nickname: str, message_json: {}, | 
					
						
							|  |  |  |                         debug: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     """Handles receiving an availability update
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-12-25 23:51:19 +00:00
										 |  |  |     if not message_json.get('type'): | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-25 23:51:19 +00:00
										 |  |  |     if not message_json['type'] == 'Availability': | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-26 17:15:04 +00:00
										 |  |  |     if not has_actor(message_json, debug): | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-26 17:12:07 +00:00
										 |  |  |     if not has_object_string(message_json, debug): | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     actor_nickname = get_nickname_from_actor(message_json['actor']) | 
					
						
							|  |  |  |     if actor_nickname != nickname: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     domain, _ = get_domain_from_actor(message_json['actor']) | 
					
						
							| 
									
										
										
										
											2021-12-25 23:51:19 +00:00
										 |  |  |     status = message_json['object'].replace('"', '') | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     return set_availability(base_dir, nickname, domain, status) | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def send_availability_via_server(base_dir: str, session, | 
					
						
							|  |  |  |                                  nickname: str, password: str, | 
					
						
							|  |  |  |                                  domain: str, port: int, | 
					
						
							|  |  |  |                                  http_prefix: str, | 
					
						
							|  |  |  |                                  status: str, | 
					
						
							|  |  |  |                                  cached_webfingers: {}, person_cache: {}, | 
					
						
							|  |  |  |                                  debug: bool, project_version: str, | 
					
						
							|  |  |  |                                  signing_priv_key_pem: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     """Sets the availability for a person via c2s
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not session: | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |         print('WARN: No session for send_availability_via_server') | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return 6 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-26 12:45:03 +00:00
										 |  |  |     domain_full = get_full_domain(domain, port) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     to_url = local_actor_url(http_prefix, nickname, domain_full) | 
					
						
							|  |  |  |     cc_url = to_url + '/followers' | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     new_availability_json = { | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         'type': 'Availability', | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |         'actor': to_url, | 
					
						
							| 
									
										
										
										
											2021-06-22 12:42:52 +00:00
										 |  |  |         'object': '"' + status + '"', | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |         'to': [to_url], | 
					
						
							|  |  |  |         'cc': [cc_url] | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-26 10:00:46 +00:00
										 |  |  |     handle = http_prefix + '://' + domain_full + '/@' + nickname | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # lookup the inbox for the To handle | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     wf_request = webfinger_handle(session, handle, http_prefix, | 
					
						
							|  |  |  |                                   cached_webfingers, | 
					
						
							|  |  |  |                                   domain, project_version, debug, False, | 
					
						
							|  |  |  |                                   signing_priv_key_pem) | 
					
						
							|  |  |  |     if not wf_request: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: availability webfinger failed for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     if not isinstance(wf_request, dict): | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |         print('WARN: availability webfinger for ' + handle + | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |               ' did not return a dict. ' + str(wf_request)) | 
					
						
							| 
									
										
										
										
											2020-06-23 10:41:12 +00:00
										 |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     post_to_box = 'outbox' | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # get the actor inbox for the To handle | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     origin_domain = domain | 
					
						
							|  |  |  |     (inbox_url, _, _, from_person_id, _, _, | 
					
						
							|  |  |  |      _, _) = get_person_box(signing_priv_key_pem, | 
					
						
							|  |  |  |                             origin_domain, | 
					
						
							|  |  |  |                             base_dir, session, wf_request, | 
					
						
							|  |  |  |                             person_cache, project_version, | 
					
						
							|  |  |  |                             http_prefix, nickname, | 
					
						
							|  |  |  |                             domain, post_to_box, 57262) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not inbox_url: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |             print('DEBUG: availability no ' + post_to_box + | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |                   ' was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return 3 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     if not from_person_id: | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: availability no actor was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  |         return 4 | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     auth_header = create_basic_auth_header(nickname, password) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:39:27 +00:00
										 |  |  |     headers = { | 
					
						
							|  |  |  |         'host': domain, | 
					
						
							|  |  |  |         'Content-type': 'application/json', | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |         'Authorization': auth_header | 
					
						
							| 
									
										
										
										
											2020-03-22 20:36:19 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     post_result = post_json(http_prefix, domain_full, | 
					
						
							|  |  |  |                             session, new_availability_json, [], | 
					
						
							|  |  |  |                             inbox_url, headers, 30, True) | 
					
						
							|  |  |  |     if not post_result: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |         print('WARN: availability failed to post') | 
					
						
							| 
									
										
										
										
											2019-07-19 11:38:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: c2s POST availability success') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 23:16:38 +00:00
										 |  |  |     return new_availability_json |