Begin on sendpost

master
Bob Mottram 2019-06-30 11:14:02 +01:00
parent 0edc7df517
commit 3b816df03a
3 changed files with 82 additions and 12 deletions

View File

@ -15,6 +15,7 @@ from posts import createPublicPost
from posts import deleteAllPosts from posts import deleteAllPosts
from posts import createOutbox from posts import createOutbox
from posts import archivePosts from posts import archivePosts
from posts import sendPost
from session import createSession from session import createSession
from session import getJson from session import getJson
import json import json

View File

@ -15,6 +15,21 @@ from webfinger import createWebfingerEndpoint
from webfinger import storeWebfingerEndpoint from webfinger import storeWebfingerEndpoint
from posts import createOutbox from posts import createOutbox
def getPersonKey(username: str,domain: str,keyType='public'):
"""Returns the public or private key of a person
"""
handle=username+'@'+domain
baseDir=os.getcwd()
keyFilename=baseDir+'/keys/'+keyType+'/'+handle.lower()+'.key'
if not os.path.isfile(keyFilename):
return ''
keyPem=''
with open(keyFilename, "r") as pemFile:
keyPem=pemFile.read()
if len(keyPem)<20:
return ''
return keyPem
def generateRSAKey() -> (str,str): def generateRSAKey() -> (str,str):
key = RSA.generate(2048) key = RSA.generate(2048)
privateKeyPem = key.exportKey("PEM").decode("utf-8") privateKeyPem = key.exportKey("PEM").decode("utf-8")

View File

@ -15,6 +15,7 @@ import os, shutil
from pprint import pprint from pprint import pprint
from random import randint from random import randint
from session import getJson from session import getJson
from person import getPersonKey
try: try:
from BeautifulSoup import BeautifulSoup from BeautifulSoup import BeautifulSoup
except ImportError: except ImportError:
@ -58,16 +59,28 @@ def parseUserFeed(session,feedUrl,asHeader) -> None:
for item in parseUserFeed(session,nextUrl,asHeader): for item in parseUserFeed(session,nextUrl,asHeader):
yield item yield item
def getPersonBox(session,wfRequest,boxName='inbox'):
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
personUrl = getUserUrl(wfRequest)
if not personUrl:
return None
personJson = getJson(session,personUrl,asHeader,None)
if not personJson.get(boxName):
return personPosts
personId=None
if personJson.get('id'):
personId=personJson['id']
pubKey=None
if personJson.get('publicKey'):
if personJson['publicKey'].get('publicKeyPem'):
pubKey=personJson['publicKey']['publicKeyPem']
return personJson[boxName],pubKey,personId
def getUserPosts(session,wfRequest,maxPosts,maxMentions,maxEmoji,maxAttachments,federationList) -> {}: def getUserPosts(session,wfRequest,maxPosts,maxMentions,maxEmoji,maxAttachments,federationList) -> {}:
userPosts={} userPosts={}
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'} feedUrl,pubKey,personId = getPersonBox(session,wfRequest,'outbox')
userUrl = getUserUrl(wfRequest) if not feedUrl:
if not userUrl:
return userPosts return userPosts
userJson = getJson(session,userUrl,asHeader,None)
if not userJson.get('outbox'):
return userPosts
feedUrl = userJson['outbox']
i = 0 i = 0
for item in parseUserFeed(session,feedUrl,asHeader): for item in parseUserFeed(session,feedUrl,asHeader):
@ -202,7 +215,7 @@ def getStatusNumber() -> (str,str):
conversationDate=currTime.strftime("%Y-%m-%d") conversationDate=currTime.strftime("%Y-%m-%d")
return statusNumber,published return statusNumber,published
def createPublicPost(username: str, domain: str, https: bool, content: str, followersOnly: bool, saveToFile: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}: def createPostBase(username: str, domain: str, toUrl: str, ccUrl: str, https: bool, content: str, followersOnly: bool, saveToFile: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
"""Creates a public post """Creates a public post
""" """
prefix='https' prefix='https'
@ -226,8 +239,8 @@ def createPublicPost(username: str, domain: str, https: bool, content: str, foll
'type': 'Create', 'type': 'Create',
'actor': prefix+'://'+domain+'/users/'+username, 'actor': prefix+'://'+domain+'/users/'+username,
'published': published, 'published': published,
'to': ['https://www.w3.org/ns/activitystreams#Public'], 'to': [toUrl],
'cc': [prefix+'://'+domain+'/users/'+username+'/followers'], 'cc': [ccUrl],
'object': {'id': newPostId, 'object': {'id': newPostId,
'type': 'Note', 'type': 'Note',
'summary': summary, 'summary': summary,
@ -235,8 +248,8 @@ def createPublicPost(username: str, domain: str, https: bool, content: str, foll
'published': published, 'published': published,
'url': prefix+'://'+domain+'/@'+username+'/'+statusNumber, 'url': prefix+'://'+domain+'/@'+username+'/'+statusNumber,
'attributedTo': prefix+'://'+domain+'/users/'+username, 'attributedTo': prefix+'://'+domain+'/users/'+username,
'to': ['https://www.w3.org/ns/activitystreams#Public'], 'to': [toUrl],
'cc': [prefix+'://'+domain+'/users/'+username+'/followers'], 'cc': [ccUrl],
'sensitive': sensitive, 'sensitive': sensitive,
'atomUri': prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber, 'atomUri': prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber,
'inReplyToAtomUri': inReplyToAtomUri, 'inReplyToAtomUri': inReplyToAtomUri,
@ -265,6 +278,47 @@ 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 createPublicPost(username: str, domain: str, https: bool, content: str, followersOnly: bool, saveToFile: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
"""Public post to the outbox
"""
prefix='https'
if not https:
prefix='http'
return createPostBase(username, domain, 'https://www.w3.org/ns/activitystreams#Public', prefix+'://'+domain+'/users/'+username+'/followers', https, content, followersOnly, saveToFile, inReplyTo, inReplyToAtomUri, subject)
def sendPost(session,username: str, domain: str, toUsername: str, toDomain: str, cc: str, https: bool, content: str, followersOnly: bool, saveToFile: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> int:
"""Post to another inbox
"""
prefix='https'
if not https:
prefix='http'
# lookup the inbox
handle=prefix+'://'+domain+'/@'+username
wfRequest = webfingerHandle(session,handle,True)
if not wfRequest:
return 1
inboxUrl,pubKey,toPersonId = getPersonBox(session,wfRequest,'inbox')
if not inboxUrl:
return 2
if not pubKey:
return 3
if not toPersonId:
return 4
postJsonObject=createPostBase(username, domain, toPersonId, cc, https, content, followersOnly, saveToFile, inReplyTo, inReplyToAtomUri, subject)
privateKeyPem=getPersonKey(username,domain,'private')
if len(privateKeyPem)==0:
return 5
signatureHeader = signPostHeaders(privateKeyPem, username, domain, '/inbox', https, postJsonObject)
# TODO
return 0
def createOutbox(username: str,domain: str,https: bool,itemsPerPage: int,headerOnly: bool,pageNumber=None) -> {}: def createOutbox(username: str,domain: str,https: bool,itemsPerPage: int,headerOnly: bool,pageNumber=None) -> {}:
"""Constructs the outbox feed """Constructs the outbox feed
""" """