Save posts to inbox to a queue

master
Bob Mottram 2019-07-04 11:02:56 +01:00
parent 50a2f95c9c
commit 640cf71416
3 changed files with 80 additions and 11 deletions

View File

@ -107,12 +107,14 @@ class PubServer(BaseHTTPRequestHandler):
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
"""
if not messageJson.get('type'):
if self.server.debug:
print('DEBUG: POST to outbox has no "type" parameter')
return False
if not messageJson.get('object') and messageJson.get('content'):
if messageJson['type']!='Create':
# https://www.w3.org/TR/activitypub/#object-without-create
if self.server.debug:
print('DEBUG POST to outbox: Adding Create wrapper')
print('DEBUG: POST to outbox - adding Create wrapper')
messageJson= \
outboxMessageCreateWrap(self.server.httpPrefix, \
self.postToNickname, \
@ -125,14 +127,14 @@ class PubServer(BaseHTTPRequestHandler):
messageJson.get('atomUri') and \
messageJson.get('to')):
if self.server.debug:
print('DEBUG POST to outbox: Create does not have the required parameters')
print('DEBUG: POST to outbox - Create does not have the required parameters')
return False
# https://www.w3.org/TR/activitypub/#create-activity-outbox
messageJson['object']['attributedTo']=messageJson['actor']
permittedOutboxTypes=['Create','Announce','Like','Follow','Undo','Update','Add','Remove','Block','Delete']
if messageJson['type'] not in permittedOutboxTypes:
if self.server.debug:
print('DEBUG POST to outbox: '+messageJson['type']+' is not a permitted activity type')
print('DEBUG: POST to outbox - '+messageJson['type']+' is not a permitted activity type')
return False
if messageJson.get('id'):
postId=messageJson['id']
@ -283,12 +285,14 @@ class PubServer(BaseHTTPRequestHandler):
# if this is a POST to teh outbox then check authentication
self.outboxAuthenticated=False
self.postToNickname=None
if self.path.endswith('/outbox'):
if '/users/' in self.path:
if self.headers.get('Authorization'):
if authorize(self.server.baseDir,self.path,self.headers['Authorization'],self.server.debug):
self.outboxAuthenticated=True
self.postToNickname=nickname
pathUsersSection=path.split('/users/')[1]
self.postToNickname=pathUsersSection.split('/')[0]
# TODO
print('c2s posts not supported yet')
self.send_response(405)
@ -360,9 +364,39 @@ class PubServer(BaseHTTPRequestHandler):
pprint(messageJson)
if not headers.get('keyId'):
if self.server.debug:
print('DEBUG: POST to inbox has no keyId in header')
return
if self.server.debug:
print('DEBUG: POST create session')
print('DEBUG: POST saving to inbox cache')
if '/users/' in self.path:
pathUsersSection=self.path.split('/users/')[1]
if '/' not in pathUsersSection:
if self.server.debug:
print('DEBUG: This is not a users endpoint')
else:
self.postToNickname=pathUsersSection.split('/')[0]
if self.postToNickname:
cacheFilename = \
savePostToInboxQueue(self.server.baseDir, \
self.server.httpPrefix, \
headers['keyId'], \
self.postToNickname, \
self.server.domain, \
messageJson)
if cacheFilename:
if cacheFilename not in self.server.inboxQueue:
self.server.inboxQueue.append(cacheFilename)
return
else:
print('DEBUG: POST to shared inbox')
return
currSessionTime=int(time.time())
if currSessionTime-self.server.sessionLastUpdate>1200:
self.server.sessionLastUpdate=currSessionTime
@ -449,5 +483,6 @@ def runDaemon(domain: str,port=80,httpPrefix='https',fedList=[],useTor=False,deb
httpd.GETbusy=False
httpd.POSTbusy=False
httpd.receivedMessage=False
httpd.inboxQueue=[]
print('Running ActivityPub daemon on ' + domain + ' port ' + str(port))
httpd.serve_forever()

View File

@ -10,6 +10,7 @@ import json
import os
import datetime
from utils import urlPermitted
from utils import createInboxQueueDir
def inboxMessageHasParams(messageJson: {}) -> bool:
"""Checks whether an incoming message contains expected parameters
@ -49,3 +50,26 @@ def validPublishedDate(published) -> bool:
if daysSincePublished>30:
return False
return True
def savePostToInboxQueue(baseDir: str,httpPrefix: str,keyId: str,nickname: str, domain: str,postJson: {}) -> str:
"""Saves the give json to the inbox queue for the person
keyId specifies the actor sending the post
"""
if ':' in domain:
domain=domain.split(':')[0]
if not keyId:
return None
if not postJson.get('id'):
return None
postId=postJson['id'].replace('/activity','')
newBufferItem = {
'keyId': keyid,
'post': postJson
}
inboxQueueDir = createInboxQueueDir(nickname,domain,baseDir)
filename=inboxQueueDir+'/'+postId.replace('/','#')+'.json'
with open(filename, 'w') as fp:
commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False)
return filename

View File

@ -20,16 +20,26 @@ def getStatusNumber() -> (str,str):
conversationDate=currTime.strftime("%Y-%m-%d")
return statusNumber,published
def createOutboxDir(nickname: str,domain: str,baseDir: str) -> str:
"""Create an outbox for a person and returns the feed filename and directory
def createPersonDir(nickname: str,domain: str,baseDir: str,dirname: str) -> str:
"""Create a directory for a person
"""
handle=nickname.lower()+'@'+domain.lower()
if not os.path.isdir(baseDir+'/accounts/'+handle):
os.mkdir(baseDir+'/accounts/'+handle)
outboxDir=baseDir+'/accounts/'+handle+'/outbox'
if not os.path.isdir(outboxDir):
os.mkdir(outboxDir)
return outboxDir
boxDir=baseDir+'/accounts/'+handle+'/'+dirname
if not os.path.isdir(boxDir):
os.mkdir(boxDir)
return boxDir
def createOutboxDir(nickname: str,domain: str,baseDir: str) -> str:
"""Create an outbox for a person
"""
return createPersonDir(nickname,domain,baseDir,'outbox')
def createInboxQueueDir(nickname: str,domain: str,baseDir: str) -> str:
"""Create an inbox queue and returns the feed filename and directory
"""
return createPersonDir(nickname,domain,baseDir,'queue')
def domainPermitted(domain: str, federationList: []):
if len(federationList)==0: