diff --git a/daemon.py b/daemon.py index 668ad4236..ad0a7fee9 100644 --- a/daemon.py +++ b/daemon.py @@ -67,6 +67,7 @@ from person import removeAccount from person import canRemovePost from person import personSnooze from person import personUnsnooze +from posts import removePostInteractions from posts import outboxMessageCreateWrap from posts import getPinnedPostAsJson from posts import pinPost @@ -460,32 +461,6 @@ class PubServer(BaseHTTPRequestHandler): else: print('ERROR: unable to create vote') - def _removePostInteractions(self, postJsonObject: {}) -> None: - """Removes potentially sensitive interactions from a post - This is the type of thing which would be of interest to marketers - or of saleable value to them. eg. Knowing who likes who or what. - """ - if postJsonObject.get('likes'): - postJsonObject['likes'] = {'items': []} - - removeCollections = ( - 'shares', 'replies', 'bookmarks', 'ignores' - ) - for removeName in removeCollections: - if postJsonObject.get(removeName): - postJsonObject[removeName] = {} - - if not postJsonObject.get('object'): - return - if not isinstance(postJsonObject['object'], dict): - return - if postJsonObject['object'].get('likes'): - postJsonObject['object']['likes'] = {'items': []} - - for removeName in removeCollections: - if postJsonObject['object'].get(removeName): - postJsonObject['object'][removeName] = {} - def _requestHTTP(self) -> bool: """Should a http response be given? """ @@ -7676,7 +7651,7 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return True - self._removePostInteractions(pjo) + removePostInteractions(pjo, True) if self._requestHTTP(): recentPostsCache = \ self.server.recentPostsCache @@ -7803,7 +7778,7 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return True - self._removePostInteractions(pjo) + removePostInteractions(pjo, True) if self._requestHTTP(): recentPostsCache = \ diff --git a/posts.py b/posts.py index 38fc9c00c..2d85445d6 100644 --- a/posts.py +++ b/posts.py @@ -3036,31 +3036,38 @@ def _addPostToTimeline(filePath: str, boxname: str, return False -def _removePostAttributes(postJsonObject: {}, authorized: bool) -> bool: +def removePostInteractions(postJsonObject: {}, force: bool) -> bool: """ Don't show likes, replies, bookmarks, DMs or shares (announces) to unauthorized viewers. This makes the timeline less useful to marketers and other surveillance-oriented organizations. Returns False if this is a private post """ - if authorized: - return True - if not postJsonObject.get('object'): - return True - if not isinstance(postJsonObject['object'], dict): - return True - # If it's not a public post then just don't show it - if not isPublicPost(postJsonObject): - return False + hasObject = False + if postJsonObject.get('object'): + if isinstance(postJsonObject['object'], dict): + hasObject = True + if hasObject: + postObj = postJsonObject['object'] + if not force: + # If not authorized and it's a private post + # then just don't show it within timelines + if not isPublicPost(postObj): + return False + else: + postObj = postJsonObject + # clear the likes - if postJsonObject['object'].get('likes'): - postJsonObject['object']['likes'] = {'items': []} + if postObj.get('likes'): + postObj['likes'] = { + 'items': [] + } # remove other collections removeCollections = ( 'replies', 'shares', 'bookmarks', 'ignores' ) for removeName in removeCollections: - if postJsonObject['object'].get(removeName): - postJsonObject['object'][removeName] = {} + if postObj.get(removeName): + postObj[removeName] = {} return True @@ -3294,8 +3301,9 @@ def _createBoxIndexed(recentPostsCache: {}, # created by individualPostAsHtml p['hasReplies'] = hasReplies - if not _removePostAttributes(p, authorized): - continue + if not authorized: + if not removePostInteractions(p, False): + continue boxItems['orderedItems'].append(p) diff --git a/tests.py b/tests.py index ddbe4f247..9c9213ce4 100644 --- a/tests.py +++ b/tests.py @@ -21,6 +21,7 @@ from cache import getPersonFromCache from threads import threadWithTrace from daemon import runDaemon from session import createSession +from posts import removePostInteractions from posts import getMentionedPeople from posts import validContentWarning from posts import deleteAllPosts @@ -3591,9 +3592,42 @@ def testUpdateActor(): shutil.rmtree(baseDir + '/.tests') +def testRemovePostInteractions() -> None: + print('testRemovePostInteractions') + postJsonObject = { + "type": "Create", + "object": { + "to": ["#Public"], + "likes": { + "items": ["a", "b", "c"] + }, + "replies": { + "replyStuff": ["a", "b", "c"] + }, + "shares": { + "sharesStuff": ["a", "b", "c"] + }, + "bookmarks": { + "bookmarksStuff": ["a", "b", "c"] + }, + "ignores": { + "ignoresStuff": ["a", "b", "c"] + } + } + } + removePostInteractions(postJsonObject, True) + assert postJsonObject['object']['likes']['items'] == [] + assert postJsonObject['object']['replies'] == {} + assert postJsonObject['object']['shares'] == {} + assert postJsonObject['object']['bookmarks'] == {} + assert postJsonObject['object']['ignores'] == {} + assert not removePostInteractions(postJsonObject, False) + + def runAllTests(): print('Running tests...') testFunctions() + testRemovePostInteractions() testExtractPGPPublicKey() testEmojiImages() testCamelCaseSplit()