From 5d9f972a5d1f9fc60f8d1bc24de578cc8fe39dd1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 8 Jul 2019 23:12:24 +0100 Subject: [PATCH] Resolving recipients --- follow.py | 19 ++++---- inbox.py | 130 ++++++++++++++++++++++++++++++++++++++++++++---------- tests.py | 8 +--- 3 files changed, 116 insertions(+), 41 deletions(-) diff --git a/follow.py b/follow.py index bc29aad1..75ae542d 100644 --- a/follow.py +++ b/follow.py @@ -350,22 +350,21 @@ def sendFollowRequest(session,baseDir: str, \ return newFollowJson -def getFollowersOfActor(baseDir :str,actor :str) -> []: +def getFollowersOfActor(baseDir :str,actor :str,recipientsDict: {}) -> {}: """In a shared inbox if we receive a post we know who it's from and if it's addressed to followers then we need to get a list of those. This returns a list of account handles which follow the given actor and also the corresponding capability id if it exists """ - result=[] if ':' not in actor: - return result + return recipientsDict httpPrefix=actor.split(':')[0] nickname=getNicknameFromActor(actor) if not nickname: - return result + return recipientsDict domain,port=getDomainFromActor(actor) if not domain: - return result + return recipientsDict actorHandle=nickname+'@'+domain # for each of the accounts for subdir, dirs, files in os.walk(baseDir+'/accounts'): @@ -375,14 +374,14 @@ def getFollowersOfActor(baseDir :str,actor :str) -> []: if os.path.isfile(followingFilename): # does this account follow the given actor? if actorHandle in open(followingFilename).read(): - ocapFilename=baseDir+'/accounts/'+account+'/ocap/granted/'+httpPrefix+':##'+domain+':'+str(port)+'#users#'+nickname+'.json' + ocapFilename=baseDir+'/accounts/'+account+'/ocap/accept/'+httpPrefix+':##'+domain+':'+str(port)+'#users#'+nickname+'.json' if os.path.isfile(ocapFilename): with open(ocapFilename, 'r') as fp: ocapJson=commentjson.load(fp) if ocapJson.get('id'): - result.append([account,ocapJson['id']]) + recipientsDict[account]=ocapJson['id'] else: - result.append([account,None]) + recipientsDict[account]=None else: - result.append([account,None]) - return result + recipientsDict[account]=None + return recipientsDict diff --git a/inbox.py b/inbox.py index dece89d2..4603d890 100644 --- a/inbox.py +++ b/inbox.py @@ -149,29 +149,6 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False) return filename -def postedToFollowers(postJsonObject: {}) -> bool: - """Is the given post sent to followers - """ - if postJsonObject.get('object'): - if postJsonObject['object'].get('to'): - for recipient in postJsonObject['object']['to']: - if 'followers' in recipient: - return True - if postJsonObject['object'].get('cc'): - for recipient in postJsonObject['object']['cc']: - if 'followers' in recipient: - return True - - if postJsonObject.get('to'): - for recipient in postJsonObject['to']: - if 'followers' in recipient: - return True - if postJsonObject.get('cc'): - for recipient in postJsonObject['cc']: - if 'followers' in recipient: - return True - return False - def inboxCheckCapabilities(baseDir :str,nickname :str,domain :str, \ actor: str,queue: [],queueJson: {}, \ capabilityId: str,debug : bool) -> bool: @@ -225,6 +202,103 @@ def inboxCheckCapabilities(baseDir :str,nickname :str,domain :str, \ print('DEBUG: object capabilities check success') return True +def inboxPostRecipientsAdd(baseDir :str,httpPrefix :str,toList :[], \ + recipientsDict :{}, \ + domainMatch: str,domain :str, \ + actor :str) -> bool: + """Given a list of post recipients (toList) from 'to' or 'cc' parameters + populate a recipientsDict with the handle and capabilities id for each + """ + followerRecipients=False + for recipient in toList: + # is this a to a local account? + if domainMatch in recipient: + # get the handle for the local account + nickname=recipient.split(domainMatch)[1] + handle=nickname+'@'+domain + if os.path.isdir(baseDir+'/accounts/'+handle): + # are capabilities granted for this account to the + # sender (actor) of the post? + ocapFilename=baseDir+'/accounts/'+handle+'/ocap/accept/'+actor.replace('/','#')+'.json' + if os.path.isfile(ocapFilename): + # read the granted capabilities and obtain the id + with open(ocapFilename, 'r') as fp: + ocapJson=commentjson.load(fp) + if ocapJson.get('id'): + # append with the capabilities id + recipientsDict[handle]=ocapJson['id'] + else: + recipientsDict[handle]=None + else: + recipientsDict[handle]=None + if recipient.endswith('followers'): + followerRecipients=True + return followerRecipients,recipientsDict + +def inboxPostRecipients(baseDir :str,postJsonObject :{},httpPrefix :str,domain : str,port :int) -> []: + recipientsDict={} + + if not postJsonObject.get('actor'): + return recipientsDict + + if ':' in domain: + domain=domain.split(':')[0] + domainBase=domain + if port!=80 and port!=443: + domain=domain+':'+str(port) + domainMatch='/'+domain+'/users/' + + actor = postJsonObject['actor'] + # first get any specific people which the post is addressed to + + followerRecipients=False + if postJsonObject.get('object'): + if isinstance(postJsonObject['object'], dict): + if postJsonObject['object'].get('to'): + includesFollowers,recipientsDict= \ + inboxPostRecipientsAdd(baseDir,httpPrefix, \ + postJsonObject['object']['to'], \ + recipientsDict, \ + domainMatch,domainBase,actor) + if includesFollowers: + followerRecipients=True + + if postJsonObject['object'].get('cc'): + includesFollowers,recipientsDict= \ + inboxPostRecipientsAdd(baseDir,httpPrefix, \ + postJsonObject['object']['cc'], \ + recipientsDict, \ + domainMatch,domainBase,actor) + if includesFollowers: + followerRecipients=True + + if postJsonObject.get('to'): + includesFollowers,recipientsDict= \ + inboxPostRecipientsAdd(baseDir,httpPrefix, \ + postJsonObject['to'], \ + recipientsDict, \ + domainMatch,domainBase,actor) + if includesFollowers: + followerRecipients=True + + if postJsonObject.get('cc'): + includesFollowers,recipientsDict= \ + inboxPostRecipientsAdd(baseDir,httpPrefix, \ + postJsonObject['cc'], \ + recipientsDict, \ + domainMatch,domainBase,actor) + if includesFollowers: + followerRecipients=True + + if not followerRecipients: + return recipientsDict + + # now resolve the followers + recipientsDict= \ + getFollowersOfActor(baseDir,actor,recipientsDict) + + return recipientsDict + def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],ocapAlways: bool,ocapGranted: {},debug: bool) -> None: """Processes received items and moves them to the appropriate directories @@ -256,11 +330,19 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache with open(queueFilename, 'r') as fp: queueJson=commentjson.load(fp) + # get recipients list + recipientsDict=inboxPostRecipients(baseDir,queueJson['post'],httpPrefix,domain,port) + + print('*************************************') + print('Resolved recipients list:') + pprint(recipientsDict) + print('*************************************') + sentToSharedInbox=False followerOcap=[] if queueJson['post'].get('actor'): # get the followers of this actor and their capabilities ids - followerOcap=getFollowersOfActor(baseDir,queueJson['post']['actor']) + #followerOcap=getFollowersOfActor(baseDir,queueJson['post']['actor']) if queueJson['post']['actor'].endswith('/inbox'): sentToSharedInbox=True diff --git a/tests.py b/tests.py index a0fd3c3e..1f871cb4 100644 --- a/tests.py +++ b/tests.py @@ -360,12 +360,6 @@ def testFollowBetweenServers(): if os.path.isfile(aliceDir+'/accounts/alice@'+aliceDomain+'/ocap/granted/'+httpPrefix+':##'+bobDomain+':'+str(bobPort)+'#users#bob.json'): break time.sleep(1) - - actorFollows=getFollowersOfActor(aliceDir,httpPrefix+'://'+bobDomain+':'+str(bobPort)+'/users/bob') - print(str(actorFollows)) - assert len(actorFollows)==1 - assert actorFollows[0][0]=='alice@'+aliceDomain - assert actorFollows[0][1].startswith(httpPrefix+'://'+bobDomain+':'+str(bobPort)+'/caps/') print('\n\nEve tries to send to Bob') sessionEve = createSession(eveDomain,evePort,useTor) @@ -437,7 +431,7 @@ def testFollowBetweenServers(): assert 'bob@'+bobDomain in open(aliceDir+'/accounts/alice@'+aliceDomain+'/following.txt').read() os.chdir(baseDir) - shutil.rmtree(baseDir+'/.tests') + #shutil.rmtree(baseDir+'/.tests') def testFollowersOfPerson(): print('testFollowersOfPerson')