mirror of https://gitlab.com/bashrc2/epicyon
Creating posts
parent
e3eb2e3af9
commit
b508abaf9d
|
@ -2,6 +2,8 @@
|
|||
|
||||
Some experiments with ActivityPub in Python.
|
||||
|
||||
Based on the specification: https://www.w3.org/TR/activitypub
|
||||
|
||||
## Install
|
||||
|
||||
``` bash
|
||||
|
|
|
@ -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))
|
||||
|
|
44
inbox.py
44
inbox.py
|
@ -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)
|
||||
|
|
70
posts.py
70
posts.py
|
@ -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'}
|
||||
|
|
Loading…
Reference in New Issue