Creating posts

master
Bob Mottram 2019-06-29 11:08:59 +01:00
parent e3eb2e3af9
commit b508abaf9d
4 changed files with 112 additions and 13 deletions

View File

@ -2,6 +2,8 @@
Some experiments with ActivityPub in Python.
Based on the specification: https://www.w3.org/TR/activitypub
## Install
``` bash

View File

@ -11,6 +11,7 @@ from person import setPreferredUsername
from person import setBio
from webfinger import webfingerHandle
from posts import getUserPosts
from posts import createPublicPost
from session import createSession
import json
import sys
@ -32,10 +33,12 @@ session = createSession(useTor)
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(username,domain,https,True)
setPreferredUsername(username,domain,'badger')
setBio(username,domain,'Some personal info')
runDaemon(domain,port,federationList,useTor)
createPublicPost(username, domain, https, "G'day world!", False, True)
#runDaemon(domain,port,federationList,useTor)
#testHttpsig()
#sys.exit()
sys.exit()
#pprint(person)
#print('\n')
@ -53,4 +56,4 @@ maxMentions=10
maxEmoji=10
maxAttachments=5
userPosts = getUserPosts(session,wfRequest,2,maxMentions,maxEmoji,maxAttachments,federationList)
print(str(userPosts))
#print(str(userPosts))

View File

@ -8,6 +8,7 @@ __status__ = "Production"
import json
import os
import datetime
def inboxPermittedMessage(messageJson,federationList) -> bool:
""" check that we are receiving from a permitted domain
@ -40,3 +41,46 @@ def inboxPermittedMessage(messageJson,federationList) -> bool:
return False
return True
def receivePublicMessage(message) -> bool:
print("TODO")
def validPublishedDate(published):
currTime=datetime.datetime.utcnow()
pubDate=datetime.datetime.strptime(published,"%Y-%m-%dT%H:%M:%SZ")
daysSincePublished = (currTime - pubTime).days
if daysSincePublished>30:
return False
return True
def receiveMessage(message):
if not message.get('type'):
return
if message['type']!='Create':
return
if not message.get('published'):
return
# is the message too old?
if not validPublishedDate(message['published']):
return
if not message.get('to'):
return
if not message.get('id'):
return
for recipient in message['to']:
if recipient.endswith('/activitystreams#Public'):
receivePublicMessage(message)
continue
username=''
domain=''
messageId=message['id'].replace('/','_')
handle=username.lower()+'@'+domain.lower()
baseDir=os.getcwd()
if not os.path.isdir(baseDir+'/accounts/'+handle):
os.mkdir(baseDir+'/accounts/'+handle)
if not os.path.isdir(baseDir+'/accounts/'+handle+'/inbox'):
os.mkdir(baseDir+'/accounts/'+handle+'/inbox')
filename=baseDir+'/accounts/'+handle+'/inbox/'+messageId+'.json'
with open(filename, 'w') as fp:
commentjson.dump(personJson, fp, indent=4, sort_keys=False)

View File

@ -8,7 +8,11 @@ __status__ = "Production"
import requests
import json
import commentjson
import html
import datetime
import os
from pprint import pprint
from random import randint
from session import getJson
try:
@ -37,17 +41,18 @@ def getUserUrl(wfRequest) -> str:
return None
def parseUserFeed(session,feedUrl,asHeader) -> None:
feed = getJson(session,feedUrl,asHeader,None)
feedJson = getJson(session,feedUrl,asHeader,None)
pprint(feedJson)
if 'orderedItems' in feed:
if 'orderedItems' in feedJson:
for item in feed['orderedItems']:
yield item
nextUrl = None
if 'first' in feed:
if 'first' in feedJson:
nextUrl = feed['first']
elif 'next' in feed:
nextUrl = feed['next']
elif 'next' in feedJson:
nextUrl = feedJson['next']
if nextUrl:
for item in parseUserFeed(session,nextUrl,asHeader):
@ -149,28 +154,45 @@ def getUserPosts(session,wfRequest,maxPosts,maxMentions,maxEmoji,maxAttachments,
break
return userPosts
def createPublicPost(username: str, domain: str, https: bool, content: str, followersOnly: bool) -> {}:
def createOutboxDir(username: str,domain: str) -> (str,str):
"""Create an outbox for a person and returns the feed filename and directory
"""
handle=username.lower()+'@'+domain.lower()
baseDir=os.getcwd()
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)
outboxJsonFilename=baseDir+'/accounts/'+handle+'/outbox.json'
return outboxJsonFilename,outboxDir
def createPublicPost(username: str, domain: str, https: bool, content: str, followersOnly: bool, saveToFile: bool) -> {}:
"""Creates a post
"""
prefix='https'
if not https:
prefix='http'
statusNumber=str(randint(100000000000000000,999999999999999999))
currTime=datetime.datetime.utcnow()
daysSinceEpoch=(currTime - datetime.datetime(1970,1,1)).days
statusNumber=str((daysSinceEpoch*24*60*60) + (currTime.hour*60*60) + (currTime.minute*60) + currTime.second)
published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
conversationDate=currTime.strftime("%Y-%m-%d")
conversationId=str(randint(100000000,999999999))
conversationId=statusNumber
postTo='https://www.w3.org/ns/activitystreams#Public'
postCC=prefix+'://'+domain+'/users/'+username+'/followers'
if followersOnly:
postTo=postCC
postCC=''
newPostId=prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber
newPost = {
'id': prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber+'/activity',
'id': newPostId+'/activity',
'type': 'Create',
'actor': prefix+'://'+domain+'/users/'+username,
'published': published,
'to': ['https://www.w3.org/ns/activitystreams#Public'],
'cc': [prefix+'://'+domain+'/users/'+username+'/followers'],
'object': {'id': prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber,
'object': {'id': newPostId,
'type': 'Note',
'summary': None,
'inReplyTo': None,
@ -200,4 +222,32 @@ def createPublicPost(username: str, domain: str, https: bool, content: str, foll
#}
}
}
if saveToFile:
outboxJsonFilename,outboxDir = createOutboxDir(username,domain)
filename=outboxDir+'/'+newPostId.replace('/','#')+'.json'
with open(filename, 'w') as fp:
commentjson.dump(newPost, fp, indent=4, sort_keys=False)
return newPost
def createOutbox(username: str,domain: str,https: bool,noOfItems: int):
prefix='https'
if not https:
prefix='http'
outboxJsonFilename,outboxDir = createOutboxDir(username,domain)
outboxItems=0
outboxHeader = {'@context': 'https://www.w3.org/ns/activitystreams',
'first': prefix+'://'+domain+'/users/'+username+'/outbox?page=true',
'id': prefix+'://'+domain+'/users/'+username+'/outbox',
'last': prefix+'://'+domain+'/users/'+username+'/outbox?min_id=0&page=true',
'totalItems': str(outboxItems),
'type': 'OrderedCollection'}
maxMessageId=100000000000000000
minMessageId=100000000000000000
outboxItems = {'@context': 'https://www.w3.org/ns/activitystreams',
'id': prefix+'://'+domain+'/users/'+username+'/outbox?page=true',
'next': prefix+'://'+domain+'/users/'+username+'/outbox?max_id='+str(maxMessageId)+'&page=true',
'orderedItems': [
],
'partOf': prefix+'://'+domain+'/users/'+username+'/outbox',
'prev': prefix+'://'+domain+'/users/'+username+'/outbox?min_id='+str(minMessageId)+'&page=true',
'type': 'OrderedCollectionPage'}