paginated outbox

master
Bob Mottram 2019-06-29 17:47:37 +01:00
parent d486fb1d31
commit fd09d2682a
3 changed files with 60 additions and 24 deletions

View File

@ -16,6 +16,7 @@ from posts import deleteAllPosts
from posts import createOutbox from posts import createOutbox
from posts import archivePosts from posts import archivePosts
from session import createSession from session import createSession
from session import getJson
import json import json
import sys import sys
import requests import requests
@ -34,7 +35,10 @@ useTor=False
session = createSession(useTor) session = createSession(useTor)
#asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} #asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
#userFollowing = getJson(session,"",asHeader,None) #userFollowing = getJson(session,"https://mastodon.social/users/Gargron/followers?page=true",asHeader,None)
#userFollowing = getJson(session,"https://mastodon.social/users/Gargron/following?page=true",asHeader,None)
#pprint(userFollowing)
#sys.exit()
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(username,domain,https,True) privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(username,domain,https,True)
@ -43,13 +47,13 @@ setPreferredUsername(username,domain,'badger')
setBio(username,domain,'Some personal info') setBio(username,domain,'Some personal info')
#createPublicPost(username, domain, https, "G'day world!", False, True, None, None, 'Not suitable for Vogons') #createPublicPost(username, domain, https, "G'day world!", False, True, None, None, 'Not suitable for Vogons')
#archivePosts(username,domain,4) #archivePosts(username,domain,4)
#outboxJson=createOutbox(username,domain,https,3,None) outboxJson=createOutbox(username,domain,https,2,False,None)
#pprint(outboxJson) pprint(outboxJson)
runDaemon(domain,port,federationList,useTor) #runDaemon(domain,port,federationList,useTor)
#testHttpsig() #testHttpsig()
#sys.exit() sys.exit()
#pprint(person) #pprint(person)
#print('\n') #print('\n')

View File

@ -163,6 +163,22 @@ def personLookup(domain: str,path: str) -> {}:
def personOutboxJson(domain: str,path: str,https: bool,noOfItems: int) -> []: def personOutboxJson(domain: str,path: str,https: bool,noOfItems: int) -> []:
"""Obtain the outbox feed for the given person """Obtain the outbox feed for the given person
""" """
if not '/outbox' in path:
return None
# handle page numbers
pageNumber=None
if '?page=' in path:
pageNumber=path.split('?page=')[1]
if pageNumber=='true':
pageNumber=1
else:
try:
pageNumber=int(pageNumber)
except:
pass
path=path.split('?page=')[0]
if not path.endswith('/outbox'): if not path.endswith('/outbox'):
return None return None
username=None username=None
@ -174,8 +190,7 @@ def personOutboxJson(domain: str,path: str,https: bool,noOfItems: int) -> []:
return None return None
if not validUsername(username): if not validUsername(username):
return None return None
startMessageId=None return createOutbox(username,domain,https,noOfItems,headerOnly,pageNumber)
return createOutbox(username,domain,https,noOfItems,startMessageId)
def setPreferredUsername(username: str, domain: str, preferredName: str) -> bool: def setPreferredUsername(username: str, domain: str, preferredName: str) -> bool:
if len(preferredName)>32: if len(preferredName)>32:

View File

@ -259,13 +259,19 @@ def createPublicPost(username: str, domain: str, https: bool, content: str, foll
commentjson.dump(newPost, fp, indent=4, sort_keys=False) commentjson.dump(newPost, fp, indent=4, sort_keys=False)
return newPost return newPost
def createOutbox(username: str,domain: str,https: bool,noOfItems: int,startMessageId=None) -> []: def createOutbox(username: str,domain: str,https: bool,itemsPerPage: int,headerOnly: bool,pageNumber=None) -> {}:
"""Constructs the outbox feed """Constructs the outbox feed
""" """
prefix='https' prefix='https'
if not https: if not https:
prefix='http' prefix='http'
outboxDir = createOutboxDir(username,domain) outboxDir = createOutboxDir(username,domain)
pageStr='?page=true'
if pageNumber:
try:
pageStr='?page='+str(pageNumber)
except:
pass
outboxHeader = {'@context': 'https://www.w3.org/ns/activitystreams', outboxHeader = {'@context': 'https://www.w3.org/ns/activitystreams',
'first': prefix+'://'+domain+'/users/'+username+'/outbox?page=true', 'first': prefix+'://'+domain+'/users/'+username+'/outbox?page=true',
'id': prefix+'://'+domain+'/users/'+username+'/outbox', 'id': prefix+'://'+domain+'/users/'+username+'/outbox',
@ -273,14 +279,14 @@ def createOutbox(username: str,domain: str,https: bool,noOfItems: int,startMessa
'totalItems': 0, 'totalItems': 0,
'type': 'OrderedCollection'} 'type': 'OrderedCollection'}
outboxItems = {'@context': 'https://www.w3.org/ns/activitystreams', outboxItems = {'@context': 'https://www.w3.org/ns/activitystreams',
'id': prefix+'://'+domain+'/users/'+username+'/outbox?page=true', 'id': prefix+'://'+domain+'/users/'+username+'/outbox'+pageStr,
'orderedItems': [ 'orderedItems': [
], ],
'partOf': prefix+'://'+domain+'/users/'+username+'/outbox', 'partOf': prefix+'://'+domain+'/users/'+username+'/outbox',
'type': 'OrderedCollectionPage'} 'type': 'OrderedCollectionPage'}
# counter for posts loop # counter for posts loop
postCtr=0 postsOnPageCtr=0
# post filenames sorted in descending order # post filenames sorted in descending order
postsInOutbox=sorted(os.listdir(outboxDir), reverse=True) postsInOutbox=sorted(os.listdir(outboxDir), reverse=True)
@ -299,26 +305,30 @@ def createOutbox(username: str,domain: str,https: bool,noOfItems: int,startMessa
prefix+'://'+domain+'/users/'+username+'/outbox?max_id='+postId+'&page=true' prefix+'://'+domain+'/users/'+username+'/outbox?max_id='+postId+'&page=true'
# Insert posts # Insert posts
currPage=1
postsCtr=0
if not pageNumber:
pageNumber=1
for postFilename in postsInOutbox: for postFilename in postsInOutbox:
# Are we at the starting message ID yet? # Are we at the starting page yet?
if startMessageId and prevPostFilename: if prevPostFilename and currPage==pageNumber and postsCtr==0:
if '#statuses#'+startMessageId in postFilename: # update the prev entry for the last message id
# update the prev entry for the last message id postId = prevPostFilename.split('#statuses#')[1].replace('#activity','')
postId = prevPostFilename.split('#statuses#')[1].replace('#activity','') outboxHeader['prev']= \
outboxHeader['prev']= \ prefix+'://'+domain+'/users/'+username+'/outbox?min_id='+postId+'&page=true'
prefix+'://'+domain+'/users/'+username+'/outbox?min_id='+postId+'&page=true'
# get the full path of the post file # get the full path of the post file
filePath = os.path.join(outboxDir, postFilename) filePath = os.path.join(outboxDir, postFilename)
try: try:
if os.path.isfile(filePath): if os.path.isfile(filePath):
if postCtr <= noOfItems: if currPage == pageNumber and postsOnPageCtr <= itemsPerPage:
# get the post as json # get the post as json
with open(filePath, 'r') as fp: with open(filePath, 'r') as fp:
p=commentjson.load(fp) p=commentjson.load(fp)
# insert it into the outbox feed # insert it into the outbox feed
if postCtr < noOfItems: if postsOnPageCtr < itemsPerPage:
outboxItems['orderedItems'].append(p) if not headerOnly:
elif postCtr == noOfItems: outboxItems['orderedItems'].append(p)
elif postsOnPageCtr == itemsPerPage:
# if this is the last post update the next message ID # if this is the last post update the next message ID
if '/statuses/' in p['id']: if '/statuses/' in p['id']:
postId = p['id'].split('/statuses/')[1].replace('/activity','') postId = p['id'].split('/statuses/')[1].replace('/activity','')
@ -326,14 +336,21 @@ def createOutbox(username: str,domain: str,https: bool,noOfItems: int,startMessa
prefix+'://'+domain+'/users/'+ \ prefix+'://'+domain+'/users/'+ \
username+'/outbox?max_id='+ \ username+'/outbox?max_id='+ \
postId+'&page=true' postId+'&page=true'
postCtr += 1 postsOnPageCtr += 1
# remember the last post filename for use with prev # remember the last post filename for use with prev
prevPostFilename = postFilename prevPostFilename = postFilename
if postCtr > noOfItems: if postsOnPageCtr > itemsPerPage:
break break
# count the pages
postsCtr += 1
if postsCtr >= itemsPerPage:
postsCtr = 0
currPage += 1
except Exception as e: except Exception as e:
print(e) print(e)
return [outboxHeader,outboxItems] if headerOnly:
return outboxHeader
return outboxItems
def archivePosts(username: str,domain: str,maxPostsInOutbox=256) -> None: def archivePosts(username: str,domain: str,maxPostsInOutbox=256) -> None:
"""Retain a maximum number of posts within the outbox """Retain a maximum number of posts within the outbox