diff --git a/README.md b/README.md index 31e4eb71..da9cea07 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ This project is currently *pre alpha* and not recommended for any real world use * Data minimization principle. Configurable post expiry time. * Likes and repeats only visible to authorized viewers * ReplyGuy mitigation: maxmimum replies per post or posts per day + * Ability to delete or hide specific conversation threads * Commandline interface. If there's a GUI it should be a separate project. * Designed for intermittent connectivity. Assume network disruptions. * Suitable for single board computers. diff --git a/inbox.py b/inbox.py index 4d6f101d..958cb635 100644 --- a/inbox.py +++ b/inbox.py @@ -962,15 +962,18 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [], \ # copy any posts addressed to followers into the shared inbox # this avoid copying file multiple times to potentially many - # individual inboxes + # individual inboxes + # TODO This obviously bypasses object capabilities and so + # any checking will need to be handled at the time when inbox + # GET happens on individual accounts if len(recipientsDictFollowers)>0: copyfile(queueFilename, \ queueJson['destination'].replace(inboxHandle,inboxHandle)) # for posts addressed to specific accounts - for handle,capsId in recipientsDict.items(): + for handle,capsId in recipientsDict.items(): destination=queueJson['destination'].replace(inboxHandle,handle) - # check that capabilities are accepted + # check that capabilities are accepted if queueJson['post'].get('capability'): capabilityIdList=queueJson['post']['capability'] # does the capability id list within the post contain the id diff --git a/posts.py b/posts.py index a9ffac51..c803ccf3 100644 --- a/posts.py +++ b/posts.py @@ -17,6 +17,7 @@ import threading import sys import trace import time +from collections import OrderedDict from threads import threadWithTrace from cache import storePersonInCache from cache import getPersonFromCache @@ -778,10 +779,19 @@ def createOutbox(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: st return createBoxBase(baseDir,'outbox',nickname,domain,port,httpPrefix, \ itemsPerPage,headerOnly,authorized,pageNumber) +def getStatusNumberFromPostFilename(filename) -> int: + """Gets the status number from a post filename + eg. https:##testdomain.com:8085#users#testuser567#statuses#1562958506952068.json + returns 156295850695206 + """ + if '#statuses#' not in filename: + return None + return int(filename.split('#')[-1].replace('.json','')) + def createBoxBase(baseDir: str,boxname: str, \ nickname: str,domain: str,port: int,httpPrefix: str, \ itemsPerPage: int,headerOnly: bool,authorized :bool,pageNumber=None) -> {}: - """Constructs the box feed + """Constructs the box feed for a person with the given nickname """ if boxname!='inbox' and boxname!='outbox': return None @@ -816,27 +826,38 @@ def createBoxBase(baseDir: str,boxname: str, \ postsOnPageCtr=0 # post filenames sorted in descending order - postsInBox=[] - postsInPersonInbox=sorted(os.listdir(boxDir), reverse=True) + postsInBoxDict={} + postsCtr=0 + postsInPersonInbox=os.listdir(boxDir) for postFilename in postsInPersonInbox: - postsInBox.append(os.path.join(boxDir, postFilename)) + # extract the status number + statusNumber=getStatusNumberFromPostFilename(postFilename) + if statusNumber: + postsInBoxDict[statusNumber]=os.path.join(boxDir, postFilename) + postsCtr+=1 # combine the inbox for the account with the shared inbox if sharedBoxDir: - postsInSharedInbox=sorted(os.listdir(sharedBoxDir), reverse=True) + postsInSharedInbox=os.listdir(sharedBoxDir) for postFilename in postsInSharedInbox: - postsInBox.append(os.path.join(sharedBoxDir, postFilename)) + statusNumber=getStatusNumberFromPostFilename(postFilename) + if statusNumber: + postsInBoxDict[statusNumber]=os.path.join(sharedBoxDir, postFilename) + postsCtr+=1 + + # sort the list in descending order of date + postsInBox=OrderedDict(sorted(postsInBoxDict.items(),reverse=True)) # number of posts in box - boxHeader['totalItems']=len(postsInBox) + boxHeader['totalItems']=postsCtr prevPostFilename=None if not pageNumber: pageNumber=1 # Generate first and last entries within header - if len(postsInBox)>0: - lastPage=int(len(postsInBox)/itemsPerPage) + if postsCtr>0: + lastPage=int(postsCtr/itemsPerPage) if lastPage<1: lastPage=1 boxHeader['last']= \ @@ -845,7 +866,7 @@ def createBoxBase(baseDir: str,boxname: str, \ # Insert posts currPage=1 postsCtr=0 - for postFilename in postsInBox: + for statusNumber,postFilename in postsInBox.items(): # Are we at the starting page yet? if prevPostFilename and currPage==pageNumber and postsCtr==0: # update the prev entry for the last message id