| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | __filename__ = "announce.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							|  |  |  | __version__ = "1.1.0" | 
					
						
							|  |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | from utils import getStatusNumber | 
					
						
							|  |  |  | from utils import createOutboxDir | 
					
						
							| 
									
										
										
										
											2019-07-02 10:43:54 +00:00
										 |  |  | from utils import urlPermitted | 
					
						
							| 
									
										
										
										
											2019-07-11 17:55:10 +00:00
										 |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import getDomainFromActor | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  | from utils import locatePost | 
					
						
							| 
									
										
										
										
											2019-10-22 11:55:06 +00:00
										 |  |  | from utils import saveJson | 
					
						
							| 
									
										
										
										
											2020-06-06 18:34:39 +00:00
										 |  |  | from utils import undoAnnounceCollectionEntry | 
					
						
							|  |  |  | from utils import updateAnnounceCollection | 
					
						
							| 
									
										
										
										
											2019-07-11 17:55:10 +00:00
										 |  |  | from posts import sendSignedJson | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | from posts import getPersonBox | 
					
						
							|  |  |  | from session import postJson | 
					
						
							|  |  |  | from webfinger import webfingerHandle | 
					
						
							|  |  |  | from auth import createBasicAuthHeader | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def outboxAnnounce(recentPostsCache: {}, | 
					
						
							|  |  |  |                    baseDir: str, messageJson: {}, debug: bool) -> bool: | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |     """ Adds or removes announce entries from the shares collection
 | 
					
						
							|  |  |  |     within a given post | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not messageJson.get('actor'): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if not messageJson.get('type'): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if not messageJson.get('object'): | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     if messageJson['type'] == 'Announce': | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |         if not isinstance(messageJson['object'], str): | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |             return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         nickname = getNicknameFromActor(messageJson['actor']) | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |         if not nickname: | 
					
						
							|  |  |  |             print('WARN: no nickname found in '+messageJson['actor']) | 
					
						
							|  |  |  |             return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         domain, port = getDomainFromActor(messageJson['actor']) | 
					
						
							|  |  |  |         postFilename = locatePost(baseDir, nickname, domain, | 
					
						
							|  |  |  |                                   messageJson['object']) | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |         if postFilename: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |             updateAnnounceCollection(recentPostsCache, baseDir, postFilename, | 
					
						
							|  |  |  |                                      messageJson['actor'], domain, debug) | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |             return True | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     if messageJson['type'] == 'Undo': | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |         if not isinstance(messageJson['object'], dict): | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |             return False | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |         if not messageJson['object'].get('type'): | 
					
						
							|  |  |  |             return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if messageJson['object']['type'] == 'Announce': | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |             if not isinstance(messageJson['object']['object'], str): | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |                 return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |             nickname = getNicknameFromActor(messageJson['actor']) | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |             if not nickname: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 print('WARN: no nickname found in ' + messageJson['actor']) | 
					
						
							| 
									
										
										
										
											2019-09-02 09:43:43 +00:00
										 |  |  |                 return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |             domain, port = getDomainFromActor(messageJson['actor']) | 
					
						
							|  |  |  |             postFilename = locatePost(baseDir, nickname, domain, | 
					
						
							|  |  |  |                                       messageJson['object']['object']) | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |             if postFilename: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 undoAnnounceCollectionEntry(recentPostsCache, | 
					
						
							|  |  |  |                                             baseDir, postFilename, | 
					
						
							|  |  |  |                                             messageJson['actor'], | 
					
						
							|  |  |  |                                             domain, debug) | 
					
						
							| 
									
										
										
										
											2019-08-01 11:43:22 +00:00
										 |  |  |                 return True | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def announcedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool: | 
					
						
							| 
									
										
										
										
											2019-08-01 09:31:38 +00:00
										 |  |  |     """Returns True if the given post is announced by the given person
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not postJsonObject.get('object'): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if not isinstance(postJsonObject['object'], dict): | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     # not to be confused with shared items | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('shares'): | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     actorMatch = domain + '/users/' + nickname | 
					
						
							| 
									
										
										
										
											2019-08-01 09:31:38 +00:00
										 |  |  |     for item in postJsonObject['object']['shares']['items']: | 
					
						
							|  |  |  |         if item['actor'].endswith(actorMatch): | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def createAnnounce(session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |                    nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                    toUrl: str, ccUrl: str, httpPrefix: str, | 
					
						
							|  |  |  |                    objectUrl: str, saveToFile: bool, | 
					
						
							|  |  |  |                    clientToServer: bool, | 
					
						
							|  |  |  |                    sendThreads: [], postLog: [], | 
					
						
							|  |  |  |                    personCache: {}, cachedWebfingers: {}, | 
					
						
							|  |  |  |                    debug: bool, projectVersion: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  |     """Creates an announce message
 | 
					
						
							|  |  |  |     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 09:25:29 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     if not urlPermitted(objectUrl, federationList, "inbox:write"): | 
					
						
							| 
									
										
										
										
											2019-07-02 10:43:54 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-11 17:55:10 +00:00
										 |  |  |     if ':' in domain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         domain = domain.split(':')[0] | 
					
						
							|  |  |  |     fullDomain = domain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if port: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if port != 80 and port != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in domain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 fullDomain = domain + ':' + str(port) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     statusNumber, published = getStatusNumber() | 
					
						
							|  |  |  |     newAnnounceId = httpPrefix + '://' + fullDomain + \ | 
					
						
							|  |  |  |         '/users/' + nickname + '/statuses/' + statusNumber | 
					
						
							|  |  |  |     atomUriStr = httpPrefix + '://' + fullDomain + '/users/' + nickname + \ | 
					
						
							|  |  |  |         '/statuses/' + statusNumber | 
					
						
							|  |  |  |     newAnnounce = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-11 17:55:10 +00:00
										 |  |  |         'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         'atomUri': atomUriStr, | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  |         'cc': [], | 
					
						
							|  |  |  |         'id': newAnnounceId+'/activity', | 
					
						
							|  |  |  |         'object': objectUrl, | 
					
						
							|  |  |  |         'published': published, | 
					
						
							|  |  |  |         'to': [toUrl], | 
					
						
							|  |  |  |         'type': 'Announce' | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ccUrl: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if len(ccUrl) > 0: | 
					
						
							|  |  |  |             newAnnounce['cc'] = [ccUrl] | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  |     if saveToFile: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         outboxDir = createOutboxDir(nickname, domain, baseDir) | 
					
						
							|  |  |  |         filename = outboxDir + '/' + newAnnounceId.replace('/', '#') + '.json' | 
					
						
							|  |  |  |         saveJson(newAnnounce, filename) | 
					
						
							| 
									
										
										
										
											2019-07-11 17:55:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     announceNickname = None | 
					
						
							|  |  |  |     announceDomain = None | 
					
						
							|  |  |  |     announcePort = None | 
					
						
							| 
									
										
										
										
											2019-10-17 22:26:47 +00:00
										 |  |  |     if '/users/' in objectUrl or \ | 
					
						
							|  |  |  |        '/channel/' in objectUrl or \ | 
					
						
							|  |  |  |        '/profile/' in objectUrl: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         announceNickname = getNicknameFromActor(objectUrl) | 
					
						
							|  |  |  |         announceDomain, announcePort = getDomainFromActor(objectUrl) | 
					
						
							| 
									
										
										
										
											2019-07-11 17:55:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if announceNickname and announceDomain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         sendSignedJson(newAnnounce, session, baseDir, | 
					
						
							|  |  |  |                        nickname, domain, port, | 
					
						
							|  |  |  |                        announceNickname, announceDomain, announcePort, None, | 
					
						
							|  |  |  |                        httpPrefix, True, clientToServer, federationList, | 
					
						
							|  |  |  |                        sendThreads, postLog, cachedWebfingers, personCache, | 
					
						
							|  |  |  |                        debug, projectVersion) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  |     return newAnnounce | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def announcePublic(session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |                    nickname: str, domain: str, port: int, httpPrefix: str, | 
					
						
							|  |  |  |                    objectUrl: str, clientToServer: bool, | 
					
						
							|  |  |  |                    sendThreads: [], postLog: [], | 
					
						
							|  |  |  |                    personCache: {}, cachedWebfingers: {}, | 
					
						
							|  |  |  |                    debug: bool, projectVersion: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-02 09:25:29 +00:00
										 |  |  |     """Makes a public announcement
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     fromDomain = domain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if port: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if port != 80 and port != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in domain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 fromDomain = domain + ':' + str(port) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toUrl = 'https://www.w3.org/ns/activitystreams#Public' | 
					
						
							|  |  |  |     ccUrl = httpPrefix + '://' + fromDomain + '/users/' + nickname + \ | 
					
						
							|  |  |  |         '/followers' | 
					
						
							|  |  |  |     return createAnnounce(session, baseDir, federationList, | 
					
						
							|  |  |  |                           nickname, domain, port, | 
					
						
							|  |  |  |                           toUrl, ccUrl, httpPrefix, | 
					
						
							|  |  |  |                           objectUrl, True, clientToServer, | 
					
						
							|  |  |  |                           sendThreads, postLog, | 
					
						
							|  |  |  |                           personCache, cachedWebfingers, | 
					
						
							|  |  |  |                           debug, projectVersion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def repeatPost(session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |                nickname: str, domain: str, port: int, httpPrefix: str, | 
					
						
							|  |  |  |                announceNickname: str, announceDomain: str, | 
					
						
							|  |  |  |                announcePort: int, announceHttpsPrefix: str, | 
					
						
							|  |  |  |                announceStatusNumber: int, clientToServer: bool, | 
					
						
							|  |  |  |                sendThreads: [], postLog: [], | 
					
						
							|  |  |  |                personCache: {}, cachedWebfingers: {}, | 
					
						
							|  |  |  |                debug: bool, projectVersion: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-02 14:02:58 +00:00
										 |  |  |     """Repeats a given status post
 | 
					
						
							| 
									
										
										
										
											2019-07-02 09:52:37 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     announcedDomain = announceDomain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if announcePort: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if announcePort != 80 and announcePort != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in announcedDomain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 announcedDomain = announcedDomain + ':' + str(announcePort) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     objectUrl = announceHttpsPrefix + '://' + announcedDomain + '/users/' + \ | 
					
						
							|  |  |  |         announceNickname + '/statuses/' + str(announceStatusNumber) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return announcePublic(session, baseDir, federationList, | 
					
						
							|  |  |  |                           nickname, domain, port, httpPrefix, | 
					
						
							|  |  |  |                           objectUrl, clientToServer, | 
					
						
							|  |  |  |                           sendThreads, postLog, | 
					
						
							|  |  |  |                           personCache, cachedWebfingers, | 
					
						
							|  |  |  |                           debug, projectVersion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def undoAnnounce(session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |                  nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                  toUrl: str, ccUrl: str, httpPrefix: str, | 
					
						
							|  |  |  |                  objectUrl: str, saveToFile: bool, | 
					
						
							|  |  |  |                  clientToServer: bool, | 
					
						
							|  |  |  |                  sendThreads: [], postLog: [], | 
					
						
							|  |  |  |                  personCache: {}, cachedWebfingers: {}, | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |                  debug: bool) -> {}: | 
					
						
							|  |  |  |     """Undoes an announce message
 | 
					
						
							|  |  |  |     Typically toUrl will be https://www.w3.org/ns/activitystreams#Public | 
					
						
							|  |  |  |     and ccUrl might be a specific person whose post was repeated and the | 
					
						
							|  |  |  |     objectUrl is typically the url of the message which was repeated, | 
					
						
							|  |  |  |     corresponding to url or atomUri in createPostBase | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     if not urlPermitted(objectUrl, federationList, "inbox:write"): | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ':' in domain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         domain = domain.split(':')[0] | 
					
						
							|  |  |  |     fullDomain = domain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if port: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if port != 80 and port != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in domain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 fullDomain = domain + ':' + str(port) | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     newUndoAnnounce = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |         'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, | 
					
						
							|  |  |  |         'type': 'Undo', | 
					
						
							|  |  |  |         'cc': [], | 
					
						
							|  |  |  |         'to': [toUrl], | 
					
						
							|  |  |  |         'object': { | 
					
						
							|  |  |  |             'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, | 
					
						
							|  |  |  |             'cc': [], | 
					
						
							|  |  |  |             'object': objectUrl, | 
					
						
							|  |  |  |             'to': [toUrl], | 
					
						
							|  |  |  |             'type': 'Announce' | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ccUrl: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if len(ccUrl) > 0: | 
					
						
							|  |  |  |             newUndoAnnounce['object']['cc'] = [ccUrl] | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     announceNickname = None | 
					
						
							|  |  |  |     announceDomain = None | 
					
						
							|  |  |  |     announcePort = None | 
					
						
							| 
									
										
										
										
											2019-10-17 22:26:47 +00:00
										 |  |  |     if '/users/' in objectUrl or \ | 
					
						
							|  |  |  |        '/channel/' in objectUrl or \ | 
					
						
							|  |  |  |        '/profile/' in objectUrl: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         announceNickname = getNicknameFromActor(objectUrl) | 
					
						
							|  |  |  |         announceDomain, announcePort = getDomainFromActor(objectUrl) | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if announceNickname and announceDomain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         sendSignedJson(newUndoAnnounce, session, baseDir, | 
					
						
							|  |  |  |                        nickname, domain, port, | 
					
						
							|  |  |  |                        announceNickname, announceDomain, announcePort, | 
					
						
							|  |  |  |                        'https://www.w3.org/ns/activitystreams#Public', | 
					
						
							|  |  |  |                        httpPrefix, True, clientToServer, federationList, | 
					
						
							|  |  |  |                        sendThreads, postLog, cachedWebfingers, | 
					
						
							|  |  |  |                        personCache, debug) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |     return newUndoAnnounce | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def undoAnnouncePublic(session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |                        nickname: str, domain: str, port: int, httpPrefix: str, | 
					
						
							|  |  |  |                        objectUrl: str, clientToServer: bool, | 
					
						
							|  |  |  |                        sendThreads: [], postLog: [], | 
					
						
							|  |  |  |                        personCache: {}, cachedWebfingers: {}, | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |                        debug: bool) -> {}: | 
					
						
							|  |  |  |     """Undoes a public announcement
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     fromDomain = domain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if port: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if port != 80 and port != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in domain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 fromDomain = domain + ':' + str(port) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toUrl = 'https://www.w3.org/ns/activitystreams#Public' | 
					
						
							|  |  |  |     ccUrl = httpPrefix + '://' + fromDomain + '/users/' + nickname + \ | 
					
						
							|  |  |  |         '/followers' | 
					
						
							|  |  |  |     return undoAnnounce(session, baseDir, federationList, | 
					
						
							|  |  |  |                         nickname, domain, port, | 
					
						
							|  |  |  |                         toUrl, ccUrl, httpPrefix, | 
					
						
							|  |  |  |                         objectUrl, True, clientToServer, | 
					
						
							|  |  |  |                         sendThreads, postLog, | 
					
						
							|  |  |  |                         personCache, cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |                         debug) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def undoRepeatPost(session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |                    nickname: str, domain: str, port: int, httpPrefix: str, | 
					
						
							|  |  |  |                    announceNickname: str, announceDomain: str, | 
					
						
							|  |  |  |                    announcePort: int, announceHttpsPrefix: str, | 
					
						
							|  |  |  |                    announceStatusNumber: int, clientToServer: bool, | 
					
						
							|  |  |  |                    sendThreads: [], postLog: [], | 
					
						
							|  |  |  |                    personCache: {}, cachedWebfingers: {}, | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |                    debug: bool) -> {}: | 
					
						
							|  |  |  |     """Undoes a status post repeat
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     announcedDomain = announceDomain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if announcePort: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if announcePort != 80 and announcePort != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in announcedDomain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 announcedDomain = announcedDomain + ':' + str(announcePort) | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     objectUrl = announceHttpsPrefix + '://' + announcedDomain + '/users/' + \ | 
					
						
							|  |  |  |         announceNickname + '/statuses/' + str(announceStatusNumber) | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     return undoAnnouncePublic(session, baseDir, federationList, | 
					
						
							|  |  |  |                               nickname, domain, port, httpPrefix, | 
					
						
							|  |  |  |                               objectUrl, clientToServer, | 
					
						
							|  |  |  |                               sendThreads, postLog, | 
					
						
							|  |  |  |                               personCache, cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2019-07-12 09:41:57 +00:00
										 |  |  |                               debug) | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def sendAnnounceViaServer(baseDir: str, session, | 
					
						
							|  |  |  |                           fromNickname: str, password: str, | 
					
						
							|  |  |  |                           fromDomain: str, fromPort: int, | 
					
						
							|  |  |  |                           httpPrefix: str, repeatObjectUrl: str, | 
					
						
							|  |  |  |                           cachedWebfingers: {}, personCache: {}, | 
					
						
							|  |  |  |                           debug: bool, projectVersion: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |     """Creates an announce message via c2s
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not session: | 
					
						
							|  |  |  |         print('WARN: No session for sendAnnounceViaServer') | 
					
						
							|  |  |  |         return 6 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     fromDomainFull = fromDomain | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if fromPort: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |         if fromPort != 80 and fromPort != 443: | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |             if ':' not in fromDomain: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |                 fromDomainFull = fromDomain + ':' + str(fromPort) | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     toUrl = 'https://www.w3.org/ns/activitystreams#Public' | 
					
						
							|  |  |  |     ccUrl = httpPrefix + '://' + fromDomainFull + '/users/' + fromNickname + \ | 
					
						
							|  |  |  |         '/followers' | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     statusNumber, published = getStatusNumber() | 
					
						
							|  |  |  |     newAnnounceId = httpPrefix + '://' + fromDomainFull + '/users/' + \ | 
					
						
							|  |  |  |         fromNickname + '/statuses/' + statusNumber | 
					
						
							|  |  |  |     newAnnounceJson = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |         'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname, | 
					
						
							|  |  |  |         'atomUri': newAnnounceId, | 
					
						
							|  |  |  |         'cc': [ccUrl], | 
					
						
							|  |  |  |         'id': newAnnounceId+'/activity', | 
					
						
							|  |  |  |         'object': repeatObjectUrl, | 
					
						
							|  |  |  |         'published': published, | 
					
						
							|  |  |  |         'to': [toUrl], | 
					
						
							|  |  |  |         'type': 'Announce' | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # lookup the inbox for the To handle | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     wfRequest = webfingerHandle(session, handle, httpPrefix, | 
					
						
							|  |  |  |                                 cachedWebfingers, | 
					
						
							|  |  |  |                                 fromDomain, projectVersion) | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |     if not wfRequest: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |             print('DEBUG: announce webfinger failed for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |         return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     postToBox = 'outbox' | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # get the actor inbox for the To handle | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     (inboxUrl, pubKeyId, pubKey, fromPersonId, | 
					
						
							|  |  |  |      sharedInbox, capabilityAcquisition, | 
					
						
							|  |  |  |      avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, | 
					
						
							|  |  |  |                                             personCache, | 
					
						
							|  |  |  |                                             projectVersion, httpPrefix, | 
					
						
							|  |  |  |                                             fromNickname, fromDomain, | 
					
						
							|  |  |  |                                             postToBox) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |     if not inboxUrl: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |             print('DEBUG: No ' + postToBox + ' was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |         return 3 | 
					
						
							|  |  |  |     if not fromPersonId: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |             print('DEBUG: No actor was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  |         return 4 | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     authHeader = createBasicAuthHeader(fromNickname, password) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     headers = { | 
					
						
							|  |  |  |         'host': fromDomain, | 
					
						
							|  |  |  |         'Content-type': 'application/json', | 
					
						
							| 
									
										
										
										
											2020-03-22 20:36:19 +00:00
										 |  |  |         'Authorization': authHeader | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-04-01 19:11:39 +00:00
										 |  |  |     postResult = postJson(session, newAnnounceJson, [], inboxUrl, | 
					
						
							|  |  |  |                           headers, "inbox:write") | 
					
						
							|  |  |  |     if not postResult: | 
					
						
							|  |  |  |         print('WARN: Announce not posted') | 
					
						
							| 
									
										
										
										
											2019-07-16 19:07:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: c2s POST announce success') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return newAnnounceJson |