| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  | __filename__ = "acceptreject.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2021-01-26 10:07:42 +00:00
										 |  |  | __version__ = "1.2.0" | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-15 15:08:12 +00:00
										 |  |  | __module_group__ = "ActivityPub" | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-01 00:04:27 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2020-12-23 10:57:44 +00:00
										 |  |  | from utils import hasUsersPath | 
					
						
							| 
									
										
										
										
											2020-12-16 10:30:54 +00:00
										 |  |  | from utils import getFullDomain | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | from utils import urlPermitted | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  | from utils import getDomainFromActor | 
					
						
							|  |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import domainPermitted | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  | from utils import followPerson | 
					
						
							| 
									
										
										
										
											2021-06-22 15:45:59 +00:00
										 |  |  | from utils import hasObjectDict | 
					
						
							| 
									
										
										
										
											2021-07-13 21:59:53 +00:00
										 |  |  | from utils import acctDir | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _createAcceptReject(baseDir: str, federationList: [], | 
					
						
							|  |  |  |                         nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                         toUrl: str, ccUrl: str, httpPrefix: str, | 
					
						
							|  |  |  |                         objectJson: {}, acceptType: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |     """Accepts or rejects something (eg. a follow request or offer)
 | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     Typically toUrl will be https://www.w3.org/ns/activitystreams#Public | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |     and ccUrl might be a specific person favorited or repeated and | 
					
						
							|  |  |  |     the followers url objectUrl is typically the url of the message, | 
					
						
							|  |  |  |     corresponding to url or atomUri in createPostBase | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not objectJson.get('actor'): | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:27:24 +00:00
										 |  |  |     if not urlPermitted(objectJson['actor'], federationList): | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 10:30:54 +00:00
										 |  |  |     domain = getFullDomain(domain, port) | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     newAccept = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |         'type': acceptType, | 
					
						
							| 
									
										
										
										
											2021-06-22 12:42:52 +00:00
										 |  |  |         'actor': httpPrefix + '://' + domain + '/users/' + nickname, | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |         'to': [toUrl], | 
					
						
							|  |  |  |         'cc': [], | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         'object': objectJson | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if ccUrl: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         if len(ccUrl) > 0: | 
					
						
							|  |  |  |             newAccept['cc'] = [ccUrl] | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     return newAccept | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def createAccept(baseDir: str, federationList: [], | 
					
						
							|  |  |  |                  nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                  toUrl: str, ccUrl: str, httpPrefix: str, | 
					
						
							| 
									
										
										
										
											2020-09-27 19:27:24 +00:00
										 |  |  |                  objectJson: {}) -> {}: | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     return _createAcceptReject(baseDir, federationList, | 
					
						
							|  |  |  |                                nickname, domain, port, | 
					
						
							|  |  |  |                                toUrl, ccUrl, httpPrefix, | 
					
						
							|  |  |  |                                objectJson, 'Accept') | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def createReject(baseDir: str, federationList: [], | 
					
						
							|  |  |  |                  nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                  toUrl: str, ccUrl: str, httpPrefix: str, | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |                  objectJson: {}) -> {}: | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     return _createAcceptReject(baseDir, federationList, | 
					
						
							|  |  |  |                                nickname, domain, port, | 
					
						
							|  |  |  |                                toUrl, ccUrl, | 
					
						
							|  |  |  |                                httpPrefix, objectJson, 'Reject') | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _acceptFollow(baseDir: str, domain: str, messageJson: {}, | 
					
						
							|  |  |  |                   federationList: [], debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2019-07-20 08:33:18 +00:00
										 |  |  |     """Receiving a follow Accept activity
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-06-22 15:45:59 +00:00
										 |  |  |     if not hasObjectDict(messageJson): | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if not messageJson['object'].get('type'): | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     if not messageJson['object']['type'] == 'Follow': | 
					
						
							| 
									
										
										
										
											2021-02-08 14:48:37 +00:00
										 |  |  |         if not messageJson['object']['type'] == 'Join': | 
					
						
							|  |  |  |             return | 
					
						
							| 
									
										
										
										
											2019-11-12 14:18:23 +00:00
										 |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: receiving Follow activity') | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not messageJson['object'].get('actor'): | 
					
						
							| 
									
										
										
										
											2019-11-12 14:18:23 +00:00
										 |  |  |         print('DEBUG: no actor in Follow activity') | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     # no, this isn't a mistake | 
					
						
							|  |  |  |     if not messageJson['object'].get('object'): | 
					
						
							| 
									
										
										
										
											2019-11-12 14:18:23 +00:00
										 |  |  |         print('DEBUG: no object within Follow activity') | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |     if not messageJson.get('to'): | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: No "to" parameter in follow Accept') | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: follow Accept received') | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     thisActor = messageJson['object']['actor'] | 
					
						
							|  |  |  |     nickname = getNicknameFromActor(thisActor) | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |     if not nickname: | 
					
						
							| 
									
										
										
										
											2020-09-03 09:58:32 +00:00
										 |  |  |         print('WARN: no nickname found in ' + thisActor) | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     acceptedDomain, acceptedPort = getDomainFromActor(thisActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not acceptedDomain: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-09-03 09:58:32 +00:00
										 |  |  |             print('DEBUG: domain not found in ' + thisActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if not nickname: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-09-03 09:58:32 +00:00
										 |  |  |             print('DEBUG: nickname not found in ' + thisActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if acceptedPort: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         if '/' + acceptedDomain + ':' + str(acceptedPort) + \ | 
					
						
							|  |  |  |            '/users/' + nickname not in thisActor: | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |             if debug: | 
					
						
							| 
									
										
										
										
											2020-09-03 09:58:32 +00:00
										 |  |  |                 print('Port: ' + str(acceptedPort)) | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |                 print('Expected: /' + acceptedDomain + ':' + | 
					
						
							| 
									
										
										
										
											2020-09-03 09:58:32 +00:00
										 |  |  |                       str(acceptedPort) + '/users/' + nickname) | 
					
						
							|  |  |  |                 print('Actual:   ' + thisActor) | 
					
						
							|  |  |  |                 print('DEBUG: unrecognized actor ' + thisActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |             return | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-06-22 12:42:52 +00:00
										 |  |  |         if not '/' + acceptedDomain + '/users/' + nickname in thisActor: | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |             if debug: | 
					
						
							| 
									
										
										
										
											2021-06-22 12:42:52 +00:00
										 |  |  |                 print('Expected: /' + acceptedDomain + '/users/' + nickname) | 
					
						
							| 
									
										
										
										
											2020-09-03 09:58:32 +00:00
										 |  |  |                 print('Actual:   ' + thisActor) | 
					
						
							|  |  |  |                 print('DEBUG: unrecognized actor ' + thisActor) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     followedActor = messageJson['object']['object'] | 
					
						
							|  |  |  |     followedDomain, port = getDomainFromActor(followedActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not followedDomain: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         print('DEBUG: no domain found within Follow activity object ' + | 
					
						
							| 
									
										
										
										
											2020-03-30 19:09:45 +00:00
										 |  |  |               followedActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     followedDomainFull = followedDomain | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if port: | 
					
						
							| 
									
										
										
										
											2021-06-22 12:42:52 +00:00
										 |  |  |         followedDomainFull = followedDomain + ':' + str(port) | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     followedNickname = getNicknameFromActor(followedActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not followedNickname: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         print('DEBUG: no nickname found within Follow activity object ' + | 
					
						
							| 
									
										
										
										
											2020-03-30 19:09:45 +00:00
										 |  |  |               followedActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     acceptedDomainFull = acceptedDomain | 
					
						
							| 
									
										
										
										
											2019-07-16 22:57:45 +00:00
										 |  |  |     if acceptedPort: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         acceptedDomainFull = acceptedDomain + ':' + str(acceptedPort) | 
					
						
							| 
									
										
										
										
											2019-07-16 22:57:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-22 10:50:07 +00:00
										 |  |  |     # has this person already been unfollowed? | 
					
						
							| 
									
										
										
										
											2021-07-13 21:59:53 +00:00
										 |  |  |     unfollowedFilename = \ | 
					
						
							|  |  |  |         acctDir(baseDir, nickname, acceptedDomainFull) + '/unfollowed.txt' | 
					
						
							| 
									
										
										
										
											2020-02-22 10:50:07 +00:00
										 |  |  |     if os.path.isfile(unfollowedFilename): | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         if followedNickname + '@' + followedDomainFull in \ | 
					
						
							|  |  |  |            open(unfollowedFilename).read(): | 
					
						
							| 
									
										
										
										
											2020-02-22 10:50:07 +00:00
										 |  |  |             if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |                 print('DEBUG: follow accept arrived for ' + | 
					
						
							|  |  |  |                       nickname + '@' + acceptedDomainFull + | 
					
						
							|  |  |  |                       ' from ' + followedNickname + '@' + followedDomainFull + | 
					
						
							| 
									
										
										
										
											2020-02-22 10:50:07 +00:00
										 |  |  |                       ' but they have been unfollowed') | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  |             return | 
					
						
							| 
									
										
										
										
											2020-02-22 10:50:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     if followPerson(baseDir, | 
					
						
							|  |  |  |                     nickname, acceptedDomainFull, | 
					
						
							|  |  |  |                     followedNickname, followedDomainFull, | 
					
						
							|  |  |  |                     federationList, debug): | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |             print('DEBUG: ' + nickname + '@' + acceptedDomainFull + | 
					
						
							|  |  |  |                   ' followed ' + followedNickname + '@' + followedDomainFull) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |             print('DEBUG: Unable to create follow - ' + | 
					
						
							| 
									
										
										
										
											2021-06-22 12:42:52 +00:00
										 |  |  |                   nickname + '@' + acceptedDomain + ' -> ' + | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |                   followedNickname + '@' + followedDomain) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def receiveAcceptReject(session, baseDir: str, | 
					
						
							|  |  |  |                         httpPrefix: str, domain: str, port: int, | 
					
						
							|  |  |  |                         sendThreads: [], postLog: [], cachedWebfingers: {}, | 
					
						
							|  |  |  |                         personCache: {}, messageJson: {}, federationList: [], | 
					
						
							|  |  |  |                         debug: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |     """Receives an Accept or Reject within the POST section of HTTPServer
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     if messageJson['type'] != 'Accept' and messageJson['type'] != 'Reject': | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |         return False | 
					
						
							|  |  |  |     if not messageJson.get('actor'): | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |             print('DEBUG: ' + messageJson['type'] + ' has no actor') | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2020-12-23 10:57:44 +00:00
										 |  |  |     if not hasUsersPath(messageJson['actor']): | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |             print('DEBUG: "users" or "profile" missing from actor in ' + | 
					
						
							|  |  |  |                   messageJson['type'] + '. Assuming single user instance.') | 
					
						
							|  |  |  |     domain, tempPort = getDomainFromActor(messageJson['actor']) | 
					
						
							|  |  |  |     if not domainPermitted(domain, federationList): | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |             print('DEBUG: ' + messageJson['type'] + | 
					
						
							|  |  |  |                   ' from domain not permitted - ' + domain) | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |     nickname = getNicknameFromActor(messageJson['actor']) | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |     if not nickname: | 
					
						
							| 
									
										
										
										
											2019-10-21 12:27:47 +00:00
										 |  |  |         # single user instance | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         nickname = 'dev' | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |             print('DEBUG: ' + messageJson['type'] + | 
					
						
							|  |  |  |                   ' does not contain a nickname. ' + | 
					
						
							| 
									
										
										
										
											2020-03-30 19:09:45 +00:00
										 |  |  |                   'Assuming single user instance.') | 
					
						
							| 
									
										
										
										
											2019-07-20 08:33:18 +00:00
										 |  |  |     # receive follow accept | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _acceptFollow(baseDir, domain, messageJson, federationList, debug) | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |     if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 18:16:29 +00:00
										 |  |  |         print('DEBUG: Uh, ' + messageJson['type'] + ', I guess') | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |     return True |