| 
									
										
										
										
											2020-04-03 17:01:25 +00:00
										 |  |  | __filename__ = "migrate.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2022-02-03 13:58:20 +00:00
										 |  |  | __version__ = "1.3.0" | 
					
						
							| 
									
										
										
										
											2020-04-03 17:01:25 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							| 
									
										
										
										
											2021-09-10 16:14:50 +00:00
										 |  |  | __email__ = "bob@libreserver.org" | 
					
						
							| 
									
										
										
										
											2020-04-03 17:01:25 +00:00
										 |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-15 15:08:12 +00:00
										 |  |  | __module_group__ = "Core" | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-12-26 18:46:43 +00:00
										 |  |  | from utils import is_account_dir | 
					
						
							| 
									
										
										
										
											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 12:02:29 +00:00
										 |  |  | from utils import acct_dir | 
					
						
							| 
									
										
										
										
											2021-12-26 17:53:07 +00:00
										 |  |  | from utils import has_group_type | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | from webfinger import webfinger_handle | 
					
						
							|  |  |  | from blocking import is_blocked | 
					
						
							|  |  |  | from posts import get_user_url | 
					
						
							| 
									
										
										
										
											2021-12-28 20:32:11 +00:00
										 |  |  | from follow import unfollow_account | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | from person import get_actor_json | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 17:01:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _move_following_handles_for_account(base_dir: str, | 
					
						
							|  |  |  |                                         nickname: str, domain: str, | 
					
						
							|  |  |  |                                         session, | 
					
						
							|  |  |  |                                         http_prefix: str, | 
					
						
							|  |  |  |                                         cached_webfingers: {}, | 
					
						
							|  |  |  |                                         debug: bool, | 
					
						
							|  |  |  |                                         signing_priv_key_pem: str) -> int: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     """Goes through all follows for an account and updates any that have moved
 | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     ctr = 0 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     following_filename = \ | 
					
						
							|  |  |  |         acct_dir(base_dir, nickname, domain) + '/following.txt' | 
					
						
							|  |  |  |     if not os.path.isfile(following_filename): | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |     with open(following_filename, 'r', encoding='utf-8') as fp_foll: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |         following_handles = fp_foll.readlines() | 
					
						
							|  |  |  |         for follow_handle in following_handles: | 
					
						
							|  |  |  |             follow_handle = follow_handle.strip("\n").strip("\r") | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |             ctr += \ | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                 _update_moved_handle(base_dir, nickname, domain, | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                                      follow_handle, session, | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                                      http_prefix, cached_webfingers, | 
					
						
							|  |  |  |                                      debug, signing_priv_key_pem) | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     return ctr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def _update_moved_handle(base_dir: str, nickname: str, domain: str, | 
					
						
							|  |  |  |                          handle: str, session, | 
					
						
							|  |  |  |                          http_prefix: str, cached_webfingers: {}, | 
					
						
							|  |  |  |                          debug: bool, signing_priv_key_pem: str) -> int: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     """Check if an account has moved, and if so then alter following.txt
 | 
					
						
							|  |  |  |     for each account. | 
					
						
							|  |  |  |     Returns 1 if moved, 0 otherwise | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     ctr = 0 | 
					
						
							|  |  |  |     if '@' not in handle: | 
					
						
							|  |  |  |         return ctr | 
					
						
							|  |  |  |     if len(handle) < 5: | 
					
						
							|  |  |  |         return ctr | 
					
						
							|  |  |  |     if handle.startswith('@'): | 
					
						
							|  |  |  |         handle = handle[1:] | 
					
						
							| 
									
										
										
										
											2022-01-02 14:51:02 +00:00
										 |  |  |     wf_request = webfinger_handle(session, handle, | 
					
						
							|  |  |  |                                   http_prefix, cached_webfingers, | 
					
						
							|  |  |  |                                   domain, __version__, debug, False, | 
					
						
							|  |  |  |                                   signing_priv_key_pem) | 
					
						
							|  |  |  |     if not wf_request: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         print('updateMovedHandle unable to webfinger ' + handle) | 
					
						
							|  |  |  |         return ctr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-02 14:51:02 +00:00
										 |  |  |     if not isinstance(wf_request, dict): | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         print('updateMovedHandle webfinger for ' + handle + | 
					
						
							| 
									
										
										
										
											2022-01-02 14:51:02 +00:00
										 |  |  |               ' did not return a dict. ' + str(wf_request)) | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     person_url = None | 
					
						
							| 
									
										
										
										
											2022-01-02 14:51:02 +00:00
										 |  |  |     if wf_request.get('errors'): | 
					
						
							|  |  |  |         print('wf_request error: ' + str(wf_request['errors'])) | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     if not person_url: | 
					
						
							|  |  |  |         person_url = get_user_url(wf_request, 0, debug) | 
					
						
							|  |  |  |         if not person_url: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |             return ctr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-03 21:42:26 +00:00
										 |  |  |     gnunet = False | 
					
						
							| 
									
										
										
										
											2021-12-25 17:09:22 +00:00
										 |  |  |     if http_prefix == 'gnunet': | 
					
						
							| 
									
										
										
										
											2021-07-03 21:42:26 +00:00
										 |  |  |         gnunet = True | 
					
						
							| 
									
										
										
										
											2022-04-29 13:54:13 +00:00
										 |  |  |     ipfs = False | 
					
						
							|  |  |  |     if http_prefix == 'ipfs': | 
					
						
							|  |  |  |         ipfs = True | 
					
						
							|  |  |  |     ipns = False | 
					
						
							|  |  |  |     if http_prefix == 'ipns': | 
					
						
							|  |  |  |         ipns = True | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     person_json = \ | 
					
						
							| 
									
										
										
										
											2022-04-29 13:54:13 +00:00
										 |  |  |         get_actor_json(domain, person_url, http_prefix, gnunet, ipfs, ipns, | 
					
						
							|  |  |  |                        debug, False, | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                        signing_priv_key_pem, None) | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     if not person_json: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     if not person_json.get('movedTo'): | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     moved_to_url = person_json['movedTo'] | 
					
						
							|  |  |  |     if '://' not in moved_to_url: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     if '.' not in moved_to_url: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     moved_to_nickname = get_nickname_from_actor(moved_to_url) | 
					
						
							|  |  |  |     if not moved_to_nickname: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     moved_to_domain, moved_to_port = get_domain_from_actor(moved_to_url) | 
					
						
							|  |  |  |     if not moved_to_domain: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     moved_to_domain_full = moved_to_domain | 
					
						
							|  |  |  |     if moved_to_port: | 
					
						
							|  |  |  |         if moved_to_port not in (80, 443): | 
					
						
							|  |  |  |             moved_to_domain_full = moved_to_domain + ':' + str(moved_to_port) | 
					
						
							|  |  |  |     group_account = has_group_type(base_dir, moved_to_url, None) | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |     if is_blocked(base_dir, nickname, domain, | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                   moved_to_nickname, moved_to_domain): | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         # someone that you follow has moved to a blocked domain | 
					
						
							|  |  |  |         # so just unfollow them | 
					
						
							| 
									
										
										
										
											2021-12-28 20:32:11 +00:00
										 |  |  |         unfollow_account(base_dir, nickname, domain, | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                          moved_to_nickname, moved_to_domain_full, | 
					
						
							| 
									
										
										
										
											2021-12-28 20:32:11 +00:00
										 |  |  |                          debug, group_account, 'following.txt') | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |         return ctr | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     following_filename = \ | 
					
						
							|  |  |  |         acct_dir(base_dir, nickname, domain) + '/following.txt' | 
					
						
							|  |  |  |     if os.path.isfile(following_filename): | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |         with open(following_filename, 'r', encoding='utf-8') as foll1: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |             following_handles = foll1.readlines() | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |             moved_to_handle = moved_to_nickname + '@' + moved_to_domain_full | 
					
						
							|  |  |  |             handle_lower = handle.lower() | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |             refollow_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-26 12:02:29 +00:00
										 |  |  |                 acct_dir(base_dir, nickname, domain) + '/refollow.txt' | 
					
						
							| 
									
										
										
										
											2021-01-09 17:41:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  |             # unfollow the old handle | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |             with open(following_filename, 'w+', encoding='utf-8') as foll2: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                 for follow_handle in following_handles: | 
					
						
							|  |  |  |                     if follow_handle.strip("\n").strip("\r").lower() != \ | 
					
						
							|  |  |  |                        handle_lower: | 
					
						
							|  |  |  |                         foll2.write(follow_handle) | 
					
						
							| 
									
										
										
										
											2021-01-09 18:12:36 +00:00
										 |  |  |                     else: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                         handle_nickname = handle.split('@')[0] | 
					
						
							|  |  |  |                         handle_domain = handle.split('@')[1] | 
					
						
							| 
									
										
										
										
											2021-12-28 20:32:11 +00:00
										 |  |  |                         unfollow_account(base_dir, nickname, domain, | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                                          handle_nickname, | 
					
						
							|  |  |  |                                          handle_domain, | 
					
						
							| 
									
										
										
										
											2021-12-28 20:32:11 +00:00
										 |  |  |                                          debug, group_account, 'following.txt') | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  |                         ctr += 1 | 
					
						
							|  |  |  |                         print('Unfollowed ' + handle + ' who has moved to ' + | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                               moved_to_handle) | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                         # save the new handles to the refollow list | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                         if os.path.isfile(refollow_filename): | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |                             with open(refollow_filename, 'a+', | 
					
						
							|  |  |  |                                       encoding='utf-8') as refoll: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                                 refoll.write(moved_to_handle + '\n') | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  |                         else: | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |                             with open(refollow_filename, 'w+', | 
					
						
							|  |  |  |                                       encoding='utf-8') as refoll: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                                 refoll.write(moved_to_handle + '\n') | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     followers_filename = \ | 
					
						
							| 
									
										
										
										
											2021-12-26 12:02:29 +00:00
										 |  |  |         acct_dir(base_dir, nickname, domain) + '/followers.txt' | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     if os.path.isfile(followers_filename): | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |         with open(followers_filename, 'r', encoding='utf-8') as foll3: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |             follower_handles = foll3.readlines() | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |             handle_lower = handle.lower() | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # remove followers who have moved | 
					
						
							| 
									
										
										
										
											2022-06-09 14:46:30 +00:00
										 |  |  |             with open(followers_filename, 'w+', encoding='utf-8') as foll4: | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |                 for follower_handle in follower_handles: | 
					
						
							|  |  |  |                     if follower_handle.strip("\n").strip("\r").lower() != \ | 
					
						
							|  |  |  |                        handle_lower: | 
					
						
							|  |  |  |                         foll4.write(follower_handle) | 
					
						
							| 
									
										
										
										
											2021-01-09 20:27:17 +00:00
										 |  |  |                     else: | 
					
						
							|  |  |  |                         ctr += 1 | 
					
						
							|  |  |  |                         print('Removed follower who has moved ' + handle) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     return ctr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  | def migrate_accounts(base_dir: str, session, | 
					
						
							|  |  |  |                      http_prefix: str, cached_webfingers: {}, | 
					
						
							|  |  |  |                      debug: bool, signing_priv_key_pem: str) -> int: | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     """If followed accounts change then this modifies the
 | 
					
						
							|  |  |  |     following lists for each account accordingly. | 
					
						
							|  |  |  |     Returns the number of accounts migrated | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  |     # update followers and following lists for each account | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     ctr = 0 | 
					
						
							| 
									
										
										
										
											2022-01-03 10:43:14 +00:00
										 |  |  |     for _, dirs, _ in os.walk(base_dir + '/accounts'): | 
					
						
							| 
									
										
										
										
											2019-10-31 10:36:35 +00:00
										 |  |  |         for handle in dirs: | 
					
						
							| 
									
										
										
										
											2021-12-26 18:46:43 +00:00
										 |  |  |             if not is_account_dir(handle): | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |                 continue | 
					
						
							|  |  |  |             nickname = handle.split('@')[0] | 
					
						
							|  |  |  |             domain = handle.split('@')[1] | 
					
						
							|  |  |  |             ctr += \ | 
					
						
							| 
									
										
										
										
											2021-12-29 21:55:09 +00:00
										 |  |  |                 _move_following_handles_for_account(base_dir, nickname, domain, | 
					
						
							|  |  |  |                                                     session, http_prefix, | 
					
						
							|  |  |  |                                                     cached_webfingers, debug, | 
					
						
							|  |  |  |                                                     signing_priv_key_pem) | 
					
						
							| 
									
										
										
										
											2020-12-13 22:13:45 +00:00
										 |  |  |         break | 
					
						
							| 
									
										
										
										
											2021-01-09 15:08:26 +00:00
										 |  |  |     return ctr |