| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | __filename__ = "like.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2021-01-26 10:07:42 +00:00
										 |  |  | __version__ = "1.2.0" | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							| 
									
										
										
										
											2021-09-10 16:14:50 +00:00
										 |  |  | __email__ = "bob@libreserver.org" | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-15 15:08:12 +00:00
										 |  |  | __module_group__ = "ActivityPub" | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  | import os | 
					
						
							|  |  |  | from pprint import pprint | 
					
						
							| 
									
										
										
										
											2021-10-13 11:15:06 +00:00
										 |  |  | from utils import hasObjectString | 
					
						
							| 
									
										
										
										
											2021-10-13 10:37:52 +00:00
										 |  |  | from utils import hasObjectStringObject | 
					
						
							| 
									
										
										
										
											2021-10-13 10:11:02 +00:00
										 |  |  | from utils import hasObjectStringType | 
					
						
							| 
									
										
										
										
											2021-06-26 14:21:24 +00:00
										 |  |  | from utils import removeDomainPort | 
					
						
							| 
									
										
										
										
											2021-06-22 15:45:59 +00:00
										 |  |  | from utils import hasObjectDict | 
					
						
							| 
									
										
										
										
											2020-12-23 10:57:44 +00:00
										 |  |  | from utils import hasUsersPath | 
					
						
							| 
									
										
										
										
											2020-12-16 11:04:46 +00:00
										 |  |  | from utils import getFullDomain | 
					
						
							| 
									
										
										
										
											2020-08-23 11:13:35 +00:00
										 |  |  | from utils import removeIdEnding | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  | from utils import urlPermitted | 
					
						
							| 
									
										
										
										
											2019-07-10 09:47:07 +00:00
										 |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import getDomainFromActor | 
					
						
							| 
									
										
										
										
											2019-07-11 12:29:31 +00:00
										 |  |  | from utils import locatePost | 
					
						
							| 
									
										
										
										
											2020-06-06 18:16:16 +00:00
										 |  |  | from utils import undoLikesCollectionEntry | 
					
						
							| 
									
										
										
										
											2021-07-31 13:19:45 +00:00
										 |  |  | from utils import hasGroupType | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  | from utils import localActorUrl | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  | from utils import loadJson | 
					
						
							|  |  |  | from utils import saveJson | 
					
						
							|  |  |  | from utils import removePostFromCache | 
					
						
							|  |  |  | from utils import getCachedPostFilename | 
					
						
							| 
									
										
										
										
											2019-07-11 12:29:31 +00:00
										 |  |  | from posts import sendSignedJson | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  | from session import postJson | 
					
						
							|  |  |  | from webfinger import webfingerHandle | 
					
						
							|  |  |  | from auth import createBasicAuthHeader | 
					
						
							|  |  |  | from posts import getPersonBox | 
					
						
							| 
									
										
										
										
											2019-07-11 12:29:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-10 12:16:03 +00:00
										 |  |  | def noOfLikes(postJsonObject: {}) -> int: | 
					
						
							|  |  |  |     """Returns the number of likes ona  given post
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     obj = postJsonObject | 
					
						
							|  |  |  |     if hasObjectDict(postJsonObject): | 
					
						
							|  |  |  |         obj = postJsonObject['object'] | 
					
						
							|  |  |  |     if not obj.get('likes'): | 
					
						
							|  |  |  |         return 0 | 
					
						
							|  |  |  |     if not isinstance(obj['likes'], dict): | 
					
						
							|  |  |  |         return 0 | 
					
						
							|  |  |  |     if not obj['likes'].get('items'): | 
					
						
							|  |  |  |         obj['likes']['items'] = [] | 
					
						
							|  |  |  |         obj['likes']['totalItems'] = 0 | 
					
						
							|  |  |  |     return len(obj['likes']['items']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | def likedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool: | 
					
						
							| 
									
										
										
										
											2019-08-01 09:31:38 +00:00
										 |  |  |     """Returns True if the given post is liked by the given person
 | 
					
						
							| 
									
										
										
										
											2019-08-01 09:05:09 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     if noOfLikes(postJsonObject) == 0: | 
					
						
							| 
									
										
										
										
											2019-08-01 09:05:09 +00:00
										 |  |  |         return False | 
					
						
							| 
									
										
										
										
											2020-09-05 11:00:21 +00:00
										 |  |  |     actorMatch = domain + '/users/' + nickname | 
					
						
							| 
									
										
										
										
											2021-10-15 09:13:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     obj = postJsonObject | 
					
						
							|  |  |  |     if hasObjectDict(postJsonObject): | 
					
						
							|  |  |  |         obj = postJsonObject['object'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for item in obj['likes']['items']: | 
					
						
							| 
									
										
										
										
											2019-08-01 09:05:09 +00:00
										 |  |  |         if item['actor'].endswith(actorMatch): | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _like(recentPostsCache: {}, | 
					
						
							|  |  |  |           session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |           nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |           ccList: [], httpPrefix: str, | 
					
						
							|  |  |  |           objectUrl: str, actorLiked: str, | 
					
						
							|  |  |  |           clientToServer: bool, | 
					
						
							|  |  |  |           sendThreads: [], postLog: [], | 
					
						
							|  |  |  |           personCache: {}, cachedWebfingers: {}, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |           debug: bool, projectVersion: str, | 
					
						
							|  |  |  |           signingPrivateKeyPem: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  |     """Creates a like
 | 
					
						
							| 
									
										
										
										
											2019-07-12 09:10:09 +00:00
										 |  |  |     actor is the person doing the liking | 
					
						
							|  |  |  |     'to' might be a specific person (actor) whose post was liked | 
					
						
							|  |  |  |     object is typically the url of the message which was liked | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-09-27 19:27:24 +00:00
										 |  |  |     if not urlPermitted(objectUrl, federationList): | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:04:46 +00:00
										 |  |  |     fullDomain = getFullDomain(domain, port) | 
					
						
							| 
									
										
										
										
											2019-08-07 11:02:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     newLikeJson = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  |         'type': 'Like', | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  |         'actor': localActorUrl(httpPrefix, nickname, fullDomain), | 
					
						
							| 
									
										
										
										
											2019-08-18 16:58:50 +00:00
										 |  |  |         'object': objectUrl | 
					
						
							| 
									
										
										
										
											2019-07-02 11:13:45 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-11 12:29:31 +00:00
										 |  |  |     if ccList: | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         if len(ccList) > 0: | 
					
						
							|  |  |  |             newLikeJson['cc'] = ccList | 
					
						
							| 
									
										
										
										
											2019-07-10 09:47:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Extract the domain and nickname from a statuses link | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     likedPostNickname = None | 
					
						
							|  |  |  |     likedPostDomain = None | 
					
						
							|  |  |  |     likedPostPort = None | 
					
						
							| 
									
										
										
										
											2021-07-31 13:19:45 +00:00
										 |  |  |     groupAccount = False | 
					
						
							| 
									
										
										
										
											2019-11-15 09:54:19 +00:00
										 |  |  |     if actorLiked: | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         likedPostNickname = getNicknameFromActor(actorLiked) | 
					
						
							|  |  |  |         likedPostDomain, likedPostPort = getDomainFromActor(actorLiked) | 
					
						
							| 
									
										
										
										
											2021-07-31 13:19:45 +00:00
										 |  |  |         groupAccount = hasGroupType(baseDir, actorLiked, personCache) | 
					
						
							| 
									
										
										
										
											2019-11-15 09:54:19 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2020-12-23 10:57:44 +00:00
										 |  |  |         if hasUsersPath(objectUrl): | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |             likedPostNickname = getNicknameFromActor(objectUrl) | 
					
						
							|  |  |  |             likedPostDomain, likedPostPort = getDomainFromActor(objectUrl) | 
					
						
							| 
									
										
										
										
											2021-07-31 13:19:45 +00:00
										 |  |  |             if '/' + str(likedPostNickname) + '/' in objectUrl: | 
					
						
							|  |  |  |                 actorLiked = \ | 
					
						
							|  |  |  |                     objectUrl.split('/' + likedPostNickname + '/')[0] + \ | 
					
						
							|  |  |  |                     '/' + likedPostNickname | 
					
						
							|  |  |  |                 groupAccount = hasGroupType(baseDir, actorLiked, personCache) | 
					
						
							| 
									
										
										
										
											2019-07-10 09:47:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if likedPostNickname: | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         postFilename = locatePost(baseDir, nickname, domain, objectUrl) | 
					
						
							| 
									
										
										
										
											2019-07-11 12:29:31 +00:00
										 |  |  |         if not postFilename: | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |             print('DEBUG: like baseDir: ' + baseDir) | 
					
						
							|  |  |  |             print('DEBUG: like nickname: ' + nickname) | 
					
						
							|  |  |  |             print('DEBUG: like domain: ' + domain) | 
					
						
							|  |  |  |             print('DEBUG: like objectUrl: ' + objectUrl) | 
					
						
							| 
									
										
										
										
											2019-07-11 12:29:31 +00:00
										 |  |  |             return None | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         updateLikesCollection(recentPostsCache, | 
					
						
							|  |  |  |                               baseDir, postFilename, objectUrl, | 
					
						
							| 
									
										
										
										
											2021-05-19 19:35:07 +00:00
										 |  |  |                               newLikeJson['actor'], | 
					
						
							| 
									
										
										
										
											2021-10-17 16:11:38 +00:00
										 |  |  |                               nickname, domain, debug, None) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         sendSignedJson(newLikeJson, session, baseDir, | 
					
						
							|  |  |  |                        nickname, domain, port, | 
					
						
							|  |  |  |                        likedPostNickname, likedPostDomain, likedPostPort, | 
					
						
							|  |  |  |                        'https://www.w3.org/ns/activitystreams#Public', | 
					
						
							|  |  |  |                        httpPrefix, True, clientToServer, federationList, | 
					
						
							|  |  |  |                        sendThreads, postLog, cachedWebfingers, personCache, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                        debug, projectVersion, None, groupAccount, | 
					
						
							| 
									
										
										
										
											2021-09-20 16:05:11 +00:00
										 |  |  |                        signingPrivateKeyPem, 7367374) | 
					
						
							| 
									
										
										
										
											2019-07-10 09:47:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return newLikeJson | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def likePost(recentPostsCache: {}, | 
					
						
							|  |  |  |              session, baseDir: str, federationList: [], | 
					
						
							|  |  |  |              nickname: str, domain: str, port: int, httpPrefix: str, | 
					
						
							|  |  |  |              likeNickname: str, likeDomain: str, likePort: int, | 
					
						
							|  |  |  |              ccList: [], | 
					
						
							|  |  |  |              likeStatusNumber: int, clientToServer: bool, | 
					
						
							|  |  |  |              sendThreads: [], postLog: [], | 
					
						
							|  |  |  |              personCache: {}, cachedWebfingers: {}, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |              debug: bool, projectVersion: str, | 
					
						
							|  |  |  |              signingPrivateKeyPem: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-11-15 09:54:19 +00:00
										 |  |  |     """Likes a given status post. This is only used by unit tests
 | 
					
						
							| 
									
										
										
										
											2019-07-02 14:02:58 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:04:46 +00:00
										 |  |  |     likeDomain = getFullDomain(likeDomain, likePort) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  |     actorLiked = localActorUrl(httpPrefix, likeNickname, likeDomain) | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |     objectUrl = actorLiked + '/statuses/' + str(likeStatusNumber) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     return _like(recentPostsCache, | 
					
						
							|  |  |  |                  session, baseDir, federationList, nickname, domain, port, | 
					
						
							|  |  |  |                  ccList, httpPrefix, objectUrl, actorLiked, clientToServer, | 
					
						
							|  |  |  |                  sendThreads, postLog, personCache, cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                  debug, projectVersion, signingPrivateKeyPem) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def sendLikeViaServer(baseDir: str, session, | 
					
						
							|  |  |  |                       fromNickname: str, password: str, | 
					
						
							|  |  |  |                       fromDomain: str, fromPort: int, | 
					
						
							|  |  |  |                       httpPrefix: str, likeUrl: str, | 
					
						
							|  |  |  |                       cachedWebfingers: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                       debug: bool, projectVersion: str, | 
					
						
							|  |  |  |                       signingPrivateKeyPem: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |     """Creates a like via c2s
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not session: | 
					
						
							|  |  |  |         print('WARN: No session for sendLikeViaServer') | 
					
						
							|  |  |  |         return 6 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:04:46 +00:00
										 |  |  |     fromDomainFull = getFullDomain(fromDomain, fromPort) | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  |     actor = localActorUrl(httpPrefix, fromNickname, fromDomainFull) | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     newLikeJson = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |         'type': 'Like', | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |         'actor': actor, | 
					
						
							| 
									
										
										
										
											2019-08-18 16:58:50 +00:00
										 |  |  |         'object': likeUrl | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |     handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # lookup the inbox for the To handle | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     wfRequest = webfingerHandle(session, handle, httpPrefix, | 
					
						
							|  |  |  |                                 cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                                 fromDomain, projectVersion, debug, False, | 
					
						
							|  |  |  |                                 signingPrivateKeyPem) | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |     if not wfRequest: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: like webfinger failed for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											2020-06-23 10:41:12 +00:00
										 |  |  |     if not isinstance(wfRequest, dict): | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |         print('WARN: like webfinger for ' + handle + | 
					
						
							|  |  |  |               ' did not return a dict. ' + str(wfRequest)) | 
					
						
							| 
									
										
										
										
											2020-06-23 10:41:12 +00:00
										 |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     postToBox = 'outbox' | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # get the actor inbox for the To handle | 
					
						
							| 
									
										
										
										
											2021-09-15 14:05:08 +00:00
										 |  |  |     originDomain = fromDomain | 
					
						
							| 
									
										
										
										
											2021-09-22 09:29:48 +00:00
										 |  |  |     (inboxUrl, pubKeyId, pubKey, fromPersonId, sharedInbox, avatarUrl, | 
					
						
							|  |  |  |      displayName, _) = getPersonBox(signingPrivateKeyPem, | 
					
						
							|  |  |  |                                     originDomain, | 
					
						
							|  |  |  |                                     baseDir, session, wfRequest, | 
					
						
							|  |  |  |                                     personCache, | 
					
						
							|  |  |  |                                     projectVersion, httpPrefix, | 
					
						
							|  |  |  |                                     fromNickname, fromDomain, | 
					
						
							|  |  |  |                                     postToBox, 72873) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |     if not inboxUrl: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: like no ' + postToBox + ' was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |         return 3 | 
					
						
							|  |  |  |     if not fromPersonId: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: like no actor was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  |         return 4 | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     authHeader = createBasicAuthHeader(fromNickname, password) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     headers = { | 
					
						
							|  |  |  |         'host': fromDomain, | 
					
						
							|  |  |  |         'Content-type': 'application/json', | 
					
						
							| 
									
										
										
										
											2020-03-22 20:36:19 +00:00
										 |  |  |         'Authorization': authHeader | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-20 13:39:53 +00:00
										 |  |  |     postResult = postJson(httpPrefix, fromDomainFull, | 
					
						
							|  |  |  |                           session, newLikeJson, [], inboxUrl, | 
					
						
							| 
									
										
										
										
											2021-03-21 13:35:15 +00:00
										 |  |  |                           headers, 3, True) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     if not postResult: | 
					
						
							| 
									
										
										
										
											2021-03-11 11:40:20 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('WARN: POST like failed for c2s to ' + inboxUrl) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         return 5 | 
					
						
							| 
									
										
										
										
											2019-07-17 18:33:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: c2s POST like success') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return newLikeJson | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def sendUndoLikeViaServer(baseDir: str, session, | 
					
						
							|  |  |  |                           fromNickname: str, password: str, | 
					
						
							|  |  |  |                           fromDomain: str, fromPort: int, | 
					
						
							|  |  |  |                           httpPrefix: str, likeUrl: str, | 
					
						
							|  |  |  |                           cachedWebfingers: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                           debug: bool, projectVersion: str, | 
					
						
							|  |  |  |                           signingPrivateKeyPem: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |     """Undo a like via c2s
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not session: | 
					
						
							|  |  |  |         print('WARN: No session for sendUndoLikeViaServer') | 
					
						
							|  |  |  |         return 6 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:04:46 +00:00
										 |  |  |     fromDomainFull = getFullDomain(fromDomain, fromPort) | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-14 11:13:39 +00:00
										 |  |  |     actor = localActorUrl(httpPrefix, fromNickname, fromDomainFull) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     newUndoLikeJson = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |         'type': 'Undo', | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |         'actor': actor, | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |         'object': { | 
					
						
							|  |  |  |             'type': 'Like', | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |             'actor': actor, | 
					
						
							| 
									
										
										
										
											2019-08-18 16:58:50 +00:00
										 |  |  |             'object': likeUrl | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |     handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # lookup the inbox for the To handle | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     wfRequest = webfingerHandle(session, handle, httpPrefix, | 
					
						
							|  |  |  |                                 cachedWebfingers, | 
					
						
							| 
									
										
										
										
											2021-08-31 14:17:11 +00:00
										 |  |  |                                 fromDomain, projectVersion, debug, False, | 
					
						
							|  |  |  |                                 signingPrivateKeyPem) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |     if not wfRequest: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: unlike webfinger failed for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											2020-06-23 10:41:12 +00:00
										 |  |  |     if not isinstance(wfRequest, dict): | 
					
						
							| 
									
										
										
										
											2021-03-11 11:41:14 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('WARN: unlike webfinger for ' + handle + | 
					
						
							| 
									
										
										
										
											2021-03-11 11:41:14 +00:00
										 |  |  |                   ' did not return a dict. ' + str(wfRequest)) | 
					
						
							| 
									
										
										
										
											2020-06-23 10:41:12 +00:00
										 |  |  |         return 1 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     postToBox = 'outbox' | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # get the actor inbox for the To handle | 
					
						
							| 
									
										
										
										
											2021-09-15 14:05:08 +00:00
										 |  |  |     originDomain = fromDomain | 
					
						
							| 
									
										
										
										
											2021-09-22 09:29:48 +00:00
										 |  |  |     (inboxUrl, pubKeyId, pubKey, fromPersonId, sharedInbox, avatarUrl, | 
					
						
							|  |  |  |      displayName, _) = getPersonBox(signingPrivateKeyPem, | 
					
						
							|  |  |  |                                     originDomain, | 
					
						
							|  |  |  |                                     baseDir, session, wfRequest, | 
					
						
							|  |  |  |                                     personCache, projectVersion, | 
					
						
							|  |  |  |                                     httpPrefix, fromNickname, | 
					
						
							|  |  |  |                                     fromDomain, postToBox, | 
					
						
							|  |  |  |                                     72625) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |     if not inboxUrl: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: unlike no ' + postToBox + ' was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |         return 3 | 
					
						
							|  |  |  |     if not fromPersonId: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('DEBUG: unlike no actor was found for ' + handle) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  |         return 4 | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     authHeader = createBasicAuthHeader(fromNickname, password) | 
					
						
							| 
									
										
										
										
											2020-03-22 21:16:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     headers = { | 
					
						
							|  |  |  |         'host': fromDomain, | 
					
						
							|  |  |  |         'Content-type': 'application/json', | 
					
						
							| 
									
										
										
										
											2020-03-22 20:36:19 +00:00
										 |  |  |         'Authorization': authHeader | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-20 13:39:53 +00:00
										 |  |  |     postResult = postJson(httpPrefix, fromDomainFull, | 
					
						
							|  |  |  |                           session, newUndoLikeJson, [], inboxUrl, | 
					
						
							| 
									
										
										
										
											2021-03-21 13:35:15 +00:00
										 |  |  |                           headers, 3, True) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     if not postResult: | 
					
						
							| 
									
										
										
										
											2021-03-11 11:41:14 +00:00
										 |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |             print('WARN: POST unlike failed for c2s to ' + inboxUrl) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |         return 5 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if debug: | 
					
						
							| 
									
										
										
										
											2021-03-18 10:01:01 +00:00
										 |  |  |         print('DEBUG: c2s POST unlike success') | 
					
						
							| 
									
										
										
										
											2019-07-17 19:04:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return newUndoLikeJson | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def outboxLike(recentPostsCache: {}, | 
					
						
							|  |  |  |                baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                messageJson: {}, debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  |     """ When a like request is received by the outbox from c2s
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not messageJson.get('type'): | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: like - no type') | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     if not messageJson['type'] == 'Like': | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: not a like') | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2021-10-13 11:15:06 +00:00
										 |  |  |     if not hasObjectString(messageJson, debug): | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: c2s like request arrived in outbox') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 11:13:35 +00:00
										 |  |  |     messageId = removeIdEnding(messageJson['object']) | 
					
						
							| 
									
										
										
										
											2021-06-23 21:31:50 +00:00
										 |  |  |     domain = removeDomainPort(domain) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     postFilename = locatePost(baseDir, nickname, domain, messageId) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  |     if not postFilename: | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: c2s like post not found in inbox or outbox') | 
					
						
							|  |  |  |             print(messageId) | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     updateLikesCollection(recentPostsCache, | 
					
						
							|  |  |  |                           baseDir, postFilename, messageId, | 
					
						
							| 
									
										
										
										
											2021-05-19 19:35:07 +00:00
										 |  |  |                           messageJson['actor'], | 
					
						
							| 
									
										
										
										
											2021-10-17 16:11:38 +00:00
										 |  |  |                           nickname, domain, debug, None) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:31:52 +00:00
										 |  |  |     if debug: | 
					
						
							| 
									
										
										
										
											2020-04-03 16:36:21 +00:00
										 |  |  |         print('DEBUG: post liked via c2s - ' + postFilename) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def outboxUndoLike(recentPostsCache: {}, | 
					
						
							|  |  |  |                    baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                    nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                    messageJson: {}, debug: bool) -> None: | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |     """ When an undo like request is received by the outbox from c2s
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not messageJson.get('type'): | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     if not messageJson['type'] == 'Undo': | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2021-10-13 10:11:02 +00:00
										 |  |  |     if not hasObjectStringType(messageJson, debug): | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     if not messageJson['object']['type'] == 'Like': | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: not a undo like') | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2021-10-13 10:37:52 +00:00
										 |  |  |     if not hasObjectStringObject(messageJson, debug): | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: c2s undo like request arrived in outbox') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-23 11:13:35 +00:00
										 |  |  |     messageId = removeIdEnding(messageJson['object']['object']) | 
					
						
							| 
									
										
										
										
											2021-06-23 21:31:50 +00:00
										 |  |  |     domain = removeDomainPort(domain) | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     postFilename = locatePost(baseDir, nickname, domain, messageId) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |     if not postFilename: | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: c2s undo like post not found in inbox or outbox') | 
					
						
							|  |  |  |             print(messageId) | 
					
						
							|  |  |  |         return True | 
					
						
							| 
									
										
										
										
											2020-04-01 10:44:33 +00:00
										 |  |  |     undoLikesCollectionEntry(recentPostsCache, baseDir, postFilename, | 
					
						
							|  |  |  |                              messageId, messageJson['actor'], | 
					
						
							| 
									
										
										
										
											2021-10-17 16:11:38 +00:00
										 |  |  |                              domain, debug, None) | 
					
						
							| 
									
										
										
										
											2019-07-17 19:55:24 +00:00
										 |  |  |     if debug: | 
					
						
							| 
									
										
										
										
											2020-09-05 11:00:21 +00:00
										 |  |  |         print('DEBUG: post undo liked via c2s - ' + postFilename) | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def updateLikesCollection(recentPostsCache: {}, | 
					
						
							|  |  |  |                           baseDir: str, postFilename: str, | 
					
						
							|  |  |  |                           objectUrl: str, actor: str, | 
					
						
							| 
									
										
										
										
											2021-10-17 16:11:38 +00:00
										 |  |  |                           nickname: str, domain: str, debug: bool, | 
					
						
							|  |  |  |                           postJsonObject: {}) -> None: | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |     """Updates the likes collection within a post
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-10-17 16:11:38 +00:00
										 |  |  |     if not postJsonObject: | 
					
						
							|  |  |  |         postJsonObject = loadJson(postFilename) | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |     if not postJsonObject: | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2021-09-03 12:44:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |     # remove any cached version of this post so that the | 
					
						
							|  |  |  |     # like icon is changed | 
					
						
							|  |  |  |     removePostFromCache(postJsonObject, recentPostsCache) | 
					
						
							|  |  |  |     cachedPostFilename = getCachedPostFilename(baseDir, nickname, | 
					
						
							|  |  |  |                                                domain, postJsonObject) | 
					
						
							|  |  |  |     if cachedPostFilename: | 
					
						
							|  |  |  |         if os.path.isfile(cachedPostFilename): | 
					
						
							| 
									
										
										
										
											2021-09-05 10:17:43 +00:00
										 |  |  |             try: | 
					
						
							|  |  |  |                 os.remove(cachedPostFilename) | 
					
						
							| 
									
										
										
										
											2021-11-25 18:42:38 +00:00
										 |  |  |             except OSError: | 
					
						
							| 
									
										
										
										
											2021-10-29 18:48:15 +00:00
										 |  |  |                 print('EX: updateLikesCollection unable to delete ' + | 
					
						
							|  |  |  |                       cachedPostFilename) | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-14 22:43:42 +00:00
										 |  |  |     obj = postJsonObject | 
					
						
							|  |  |  |     if hasObjectDict(postJsonObject): | 
					
						
							|  |  |  |         obj = postJsonObject['object'] | 
					
						
							| 
									
										
										
										
											2021-10-15 09:13:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |     if not objectUrl.endswith('/likes'): | 
					
						
							|  |  |  |         objectUrl = objectUrl + '/likes' | 
					
						
							| 
									
										
										
										
											2021-10-14 22:43:42 +00:00
										 |  |  |     if not obj.get('likes'): | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: Adding initial like to ' + objectUrl) | 
					
						
							|  |  |  |         likesJson = { | 
					
						
							|  |  |  |             "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							|  |  |  |             'id': objectUrl, | 
					
						
							|  |  |  |             'type': 'Collection', | 
					
						
							|  |  |  |             "totalItems": 1, | 
					
						
							|  |  |  |             'items': [{ | 
					
						
							|  |  |  |                 'type': 'Like', | 
					
						
							|  |  |  |                 'actor': actor | 
					
						
							|  |  |  |             }] | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-10-14 22:43:42 +00:00
										 |  |  |         obj['likes'] = likesJson | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-10-14 22:43:42 +00:00
										 |  |  |         if not obj['likes'].get('items'): | 
					
						
							|  |  |  |             obj['likes']['items'] = [] | 
					
						
							|  |  |  |         for likeItem in obj['likes']['items']: | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  |             if likeItem.get('actor'): | 
					
						
							|  |  |  |                 if likeItem['actor'] == actor: | 
					
						
							|  |  |  |                     # already liked | 
					
						
							|  |  |  |                     return | 
					
						
							|  |  |  |         newLike = { | 
					
						
							|  |  |  |             'type': 'Like', | 
					
						
							|  |  |  |             'actor': actor | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-10-14 22:43:42 +00:00
										 |  |  |         obj['likes']['items'].append(newLike) | 
					
						
							|  |  |  |         itlen = len(obj['likes']['items']) | 
					
						
							|  |  |  |         obj['likes']['totalItems'] = itlen | 
					
						
							| 
									
										
										
										
											2021-09-03 12:00:23 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: saving post with likes added') | 
					
						
							|  |  |  |         pprint(postJsonObject) | 
					
						
							|  |  |  |     saveJson(postJsonObject, postFilename) |