forked from indymedia/epicyon
Announce function
parent
e2de1d1b9c
commit
f609e365da
|
@ -9,5 +9,5 @@ Also: https://raw.githubusercontent.com/w3c/activitypub/gh-pages/activitypub-tut
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
sudo pacman -S python-pysocks python-pycryptodome python-beautifulsoup4
|
sudo pacman -S python-pysocks python-pycryptodome python-beautifulsoup4 python-requests-toolbelt
|
||||||
```
|
```
|
|
@ -0,0 +1,65 @@
|
||||||
|
__filename__ = "announce.py"
|
||||||
|
__author__ = "Bob Mottram"
|
||||||
|
__license__ = "AGPL3+"
|
||||||
|
__version__ = "0.0.1"
|
||||||
|
__maintainer__ = "Bob Mottram"
|
||||||
|
__email__ = "bob@freedombone.net"
|
||||||
|
__status__ = "Production"
|
||||||
|
|
||||||
|
import json
|
||||||
|
import commentjson
|
||||||
|
from utils import getStatusNumber
|
||||||
|
from utils import createOutboxDir
|
||||||
|
|
||||||
|
def createAnnounce(baseDir: str,username: str, domain: str, port: int,toUrl: str, ccUrl: str, https: bool, objectUrl: str, saveToFile: bool) -> {}:
|
||||||
|
"""Creates an announce message
|
||||||
|
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
|
||||||
|
and ccUrl might be a specific person favorited or repeated and the followers url
|
||||||
|
objectUrl is typically the url of the message, corresponding to url or atomUri in createPostBase
|
||||||
|
"""
|
||||||
|
prefix='https'
|
||||||
|
if not https:
|
||||||
|
prefix='http'
|
||||||
|
|
||||||
|
if port!=80 and port!=443:
|
||||||
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
|
statusNumber,published = getStatusNumber()
|
||||||
|
newAnnounceId=prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber
|
||||||
|
newAnnounce = {
|
||||||
|
'actor': prefix+'://'+domain+'/users/'+username,
|
||||||
|
'atomUri': prefix+'://'+domain+'/users/'+username+'/statuses/'+statusNumber,
|
||||||
|
'cc': [],
|
||||||
|
'id': newAnnounceId+'/activity',
|
||||||
|
'object': objectUrl,
|
||||||
|
'published': published,
|
||||||
|
'to': [toUrl],
|
||||||
|
'type': 'Announce'
|
||||||
|
}
|
||||||
|
if ccUrl:
|
||||||
|
if len(ccUrl)>0:
|
||||||
|
newAnnounce['cc']=ccUrl
|
||||||
|
if saveToFile:
|
||||||
|
if ':' in domain:
|
||||||
|
domain=domain.split(':')[0]
|
||||||
|
outboxDir = createOutboxDir(username,domain,baseDir)
|
||||||
|
filename=outboxDir+'/'+newAnnounceId.replace('/','#')+'.json'
|
||||||
|
with open(filename, 'w') as fp:
|
||||||
|
commentjson.dump(newAnnounce, fp, indent=4, sort_keys=False)
|
||||||
|
return newAnnounce
|
||||||
|
|
||||||
|
def announcePublic(baseDir: str,username: str, domain: str, port: int, https: bool, objectUrl: str, saveToFile: bool) -> {}:
|
||||||
|
"""Makes a public announcement
|
||||||
|
"""
|
||||||
|
prefix='https'
|
||||||
|
if not https:
|
||||||
|
prefix='http'
|
||||||
|
|
||||||
|
fromDomain=domain
|
||||||
|
if port!=80 and port!=443:
|
||||||
|
fromDomain=fromDomain+':'+str(port)
|
||||||
|
|
||||||
|
toUrl = 'https://www.w3.org/ns/activitystreams#Public'
|
||||||
|
ccUrl = prefix + '://'+fromDomain+'/users/'+username+'/followers'
|
||||||
|
return createAnnounce(baseDir,username, domain, port,toUrl, ccUrl, https, objectUrl, saveToFile)
|
||||||
|
|
10
daemon.py
10
daemon.py
|
@ -220,7 +220,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
currSessionTime=int(time.time())
|
currSessionTime=int(time.time())
|
||||||
if currSessionTime-self.server.sessionLastUpdate>600:
|
if currSessionTime-self.server.sessionLastUpdate>600:
|
||||||
self.server.sessionLastUpdate=currSessionTime
|
self.server.sessionLastUpdate=currSessionTime
|
||||||
self.server.session = createSession(self.server.useTor)
|
self.server.session = createSession(self.server.domain,self.server.port,self.server.useTor)
|
||||||
print('**************** POST get public key of '+personUrl+' from '+self.server.baseDir)
|
print('**************** POST get public key of '+personUrl+' from '+self.server.baseDir)
|
||||||
pubKey=getPersonPubKey(self.server.session,personUrl,self.server.personCache)
|
pubKey=getPersonPubKey(self.server.session,personUrl,self.server.personCache)
|
||||||
if not pubKey:
|
if not pubKey:
|
||||||
|
@ -230,6 +230,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.server.POSTbusy=False
|
self.server.POSTbusy=False
|
||||||
return
|
return
|
||||||
print('**************** POST check signature')
|
print('**************** POST check signature')
|
||||||
|
if not verifyPostHeaders(self.server.https, pubKey, self.headers, '/inbox' ,False, json.dumps(messageJson)):
|
||||||
|
print('**************** POST signature verification failed')
|
||||||
|
self.send_response(401)
|
||||||
|
self.end_headers()
|
||||||
|
self.server.POSTbusy=False
|
||||||
|
return
|
||||||
print('**************** POST valid')
|
print('**************** POST valid')
|
||||||
pprint(messageJson)
|
pprint(messageJson)
|
||||||
# add a property to the object, just to mess with data
|
# add a property to the object, just to mess with data
|
||||||
|
@ -261,7 +267,7 @@ def runDaemon(domain: str,port=80,https=True,fedList=[],useTor=False) -> None:
|
||||||
httpd.personCache={}
|
httpd.personCache={}
|
||||||
httpd.cachedWebfingers={}
|
httpd.cachedWebfingers={}
|
||||||
httpd.useTor=useTor
|
httpd.useTor=useTor
|
||||||
httpd.session = createSession(useTor)
|
httpd.session = createSession(domain,port,useTor)
|
||||||
httpd.sessionLastUpdate=int(time.time())
|
httpd.sessionLastUpdate=int(time.time())
|
||||||
httpd.lastGET=0
|
httpd.lastGET=0
|
||||||
httpd.lastPOST=0
|
httpd.lastPOST=0
|
||||||
|
|
21
epicyon.py
21
epicyon.py
|
@ -10,7 +10,7 @@ from person import createPerson
|
||||||
from person import setPreferredUsername
|
from person import setPreferredUsername
|
||||||
from person import setBio
|
from person import setBio
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from posts import getUserPosts
|
from posts import getPosts
|
||||||
from posts import createPublicPost
|
from posts import createPublicPost
|
||||||
from posts import deleteAllPosts
|
from posts import deleteAllPosts
|
||||||
from posts import createOutbox
|
from posts import createOutbox
|
||||||
|
@ -35,6 +35,7 @@ from follow import unfollowPerson
|
||||||
from follow import unfollowerOfPerson
|
from follow import unfollowerOfPerson
|
||||||
from tests import testPostMessageBetweenServers
|
from tests import testPostMessageBetweenServers
|
||||||
from tests import runAllTests
|
from tests import runAllTests
|
||||||
|
from announce import announcePublic
|
||||||
|
|
||||||
runAllTests()
|
runAllTests()
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ port=6227
|
||||||
https=False
|
https=False
|
||||||
useTor=False
|
useTor=False
|
||||||
baseDir=os.getcwd()
|
baseDir=os.getcwd()
|
||||||
session = createSession(useTor)
|
session = createSession(domain,port,useTor)
|
||||||
personCache={}
|
personCache={}
|
||||||
cachedWebfingers={}
|
cachedWebfingers={}
|
||||||
|
|
||||||
|
@ -84,11 +85,11 @@ setBio(baseDir,username,domain,'Some personal info')
|
||||||
#outboxJson=createOutbox(baseDir,username,domain,port,https,2,True,None)
|
#outboxJson=createOutbox(baseDir,username,domain,port,https,2,True,None)
|
||||||
#pprint(outboxJson)
|
#pprint(outboxJson)
|
||||||
|
|
||||||
testPostMessageBetweenServers()
|
#testPostMessageBetweenServers()
|
||||||
#runDaemon(domain,port,https,federationList,useTor)
|
#runDaemon(domain,port,https,federationList,useTor)
|
||||||
|
|
||||||
#testHttpsig()
|
#testHttpsig()
|
||||||
sys.exit()
|
#sys.exit()
|
||||||
|
|
||||||
#pprint(person)
|
#pprint(person)
|
||||||
#print('\n')
|
#print('\n')
|
||||||
|
@ -99,16 +100,16 @@ wfRequest = webfingerHandle(session,handle,True,cachedWebfingers)
|
||||||
if not wfRequest:
|
if not wfRequest:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
personJson,pubKeyId,pubKey,personId=getPersonBox(session,wfRequest,personCache)
|
personUrl,pubKeyId,pubKey,personId=getPersonBox(session,wfRequest,personCache,'outbox')
|
||||||
pprint(personJson)
|
#pprint(personUrl)
|
||||||
sys.exit()
|
#sys.exit()
|
||||||
|
|
||||||
wfResult = json.dumps(wfRequest, indent=4, sort_keys=True)
|
wfResult = json.dumps(wfRequest, indent=4, sort_keys=True)
|
||||||
print(str(wfResult))
|
#print(str(wfResult))
|
||||||
sys.exit()
|
#sys.exit()
|
||||||
|
|
||||||
maxMentions=10
|
maxMentions=10
|
||||||
maxEmoji=10
|
maxEmoji=10
|
||||||
maxAttachments=5
|
maxAttachments=5
|
||||||
userPosts = getUserPosts(session,wfRequest,2,maxMentions,maxEmoji,maxAttachments,federationList)
|
userPosts = getPosts(session,personUrl,10,maxMentions,maxEmoji,maxAttachments,federationList,personCache)
|
||||||
#print(str(userPosts))
|
#print(str(userPosts))
|
||||||
|
|
44
posts.py
44
posts.py
|
@ -26,6 +26,8 @@ from session import getJson
|
||||||
from session import postJson
|
from session import postJson
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from httpsig import createSignedHeader
|
from httpsig import createSignedHeader
|
||||||
|
from utils import getStatusNumber
|
||||||
|
from utils import createOutboxDir
|
||||||
try:
|
try:
|
||||||
from BeautifulSoup import BeautifulSoup
|
from BeautifulSoup import BeautifulSoup
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -113,6 +115,7 @@ def getPersonPubKey(session,personUrl: str,personCache: {}) -> str:
|
||||||
return None
|
return None
|
||||||
personJson = getPersonFromCache(personUrl,personCache)
|
personJson = getPersonFromCache(personUrl,personCache)
|
||||||
if not personJson:
|
if not personJson:
|
||||||
|
print('************Obtaining public key for '+personUrl)
|
||||||
personJson = getJson(session,personUrl,asHeader,None)
|
personJson = getJson(session,personUrl,asHeader,None)
|
||||||
pubKey=None
|
pubKey=None
|
||||||
if personJson.get('publicKey'):
|
if personJson.get('publicKey'):
|
||||||
|
@ -122,14 +125,15 @@ def getPersonPubKey(session,personUrl: str,personCache: {}) -> str:
|
||||||
storePersonInCache(personUrl,personJson,personCache)
|
storePersonInCache(personUrl,personJson,personCache)
|
||||||
return pubKey
|
return pubKey
|
||||||
|
|
||||||
def getUserPosts(session,wfRequest: {},maxPosts: int,maxMentions: int,maxEmoji: int,maxAttachments: int,federationList: [],personCache: {}) -> {}:
|
def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int,maxEmoji: int,maxAttachments: int,federationList: [],personCache: {}) -> {}:
|
||||||
userPosts={}
|
personPosts={}
|
||||||
feedUrl,pubKeyId,pubKey,personId = getPersonBox(session,wfRequest,personCache,'outbox')
|
if not outboxUrl:
|
||||||
if not feedUrl:
|
return personPosts
|
||||||
return userPosts
|
|
||||||
|
|
||||||
|
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
|
||||||
i = 0
|
i = 0
|
||||||
for item in parseUserFeed(session,feedUrl,asHeader):
|
for item in parseUserFeed(session,outboxUrl,asHeader):
|
||||||
|
pprint(item)
|
||||||
if not item.get('type'):
|
if not item.get('type'):
|
||||||
continue
|
continue
|
||||||
if item['type'] != 'Create':
|
if item['type'] != 'Create':
|
||||||
|
@ -137,7 +141,7 @@ def getUserPosts(session,wfRequest: {},maxPosts: int,maxMentions: int,maxEmoji:
|
||||||
if not item.get('object'):
|
if not item.get('object'):
|
||||||
continue
|
continue
|
||||||
published = item['object']['published']
|
published = item['object']['published']
|
||||||
if not userPosts.get(published):
|
if not personPosts.get(published):
|
||||||
content = item['object']['content']
|
content = item['object']['content']
|
||||||
|
|
||||||
mentions=[]
|
mentions=[]
|
||||||
|
@ -195,7 +199,7 @@ def getUserPosts(session,wfRequest: {},maxPosts: int,maxMentions: int,maxEmoji:
|
||||||
if item['object'].get('sensitive'):
|
if item['object'].get('sensitive'):
|
||||||
sensitive = item['object']['sensitive']
|
sensitive = item['object']['sensitive']
|
||||||
|
|
||||||
userPosts[published] = {
|
personPosts[published] = {
|
||||||
"sensitive": sensitive,
|
"sensitive": sensitive,
|
||||||
"inreplyto": inReplyTo,
|
"inreplyto": inReplyTo,
|
||||||
"summary": summary,
|
"summary": summary,
|
||||||
|
@ -211,18 +215,7 @@ def getUserPosts(session,wfRequest: {},maxPosts: int,maxMentions: int,maxEmoji:
|
||||||
|
|
||||||
if i == maxPosts:
|
if i == maxPosts:
|
||||||
break
|
break
|
||||||
return userPosts
|
return personPosts
|
||||||
|
|
||||||
def createOutboxDir(username: str,domain: str,baseDir: str) -> str:
|
|
||||||
"""Create an outbox for a person and returns the feed filename and directory
|
|
||||||
"""
|
|
||||||
handle=username.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
|
|
||||||
|
|
||||||
def createOutboxArchive(username: str,domain: str,baseDir: str) -> str:
|
def createOutboxArchive(username: str,domain: str,baseDir: str) -> str:
|
||||||
"""Creates an archive directory for outbox posts
|
"""Creates an archive directory for outbox posts
|
||||||
|
@ -247,17 +240,6 @@ def deleteAllPosts(username: str, domain: str,baseDir: str) -> None:
|
||||||
elif os.path.isdir(filePath): shutil.rmtree(filePath)
|
elif os.path.isdir(filePath): shutil.rmtree(filePath)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
def getStatusNumber() -> (str,str):
|
|
||||||
"""Returns the status number and published date
|
|
||||||
"""
|
|
||||||
currTime=datetime.datetime.utcnow()
|
|
||||||
daysSinceEpoch=(currTime - datetime.datetime(1970,1,1)).days
|
|
||||||
# status is the number of seconds since epoch
|
|
||||||
statusNumber=str(((daysSinceEpoch*24*60*60) + (currTime.hour*60*60) + (currTime.minute*60) + currTime.second)*1000000 + currTime.microsecond)
|
|
||||||
published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
conversationDate=currTime.strftime("%Y-%m-%d")
|
|
||||||
return statusNumber,published
|
|
||||||
|
|
||||||
def createPostBase(baseDir: str,username: str, domain: str, port: int,toUrl: str, ccUrl: str, https: bool, content: str, followersOnly: bool, saveToFile: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
def createPostBase(baseDir: str,username: str, domain: str, port: int,toUrl: str, ccUrl: str, https: bool, content: str, followersOnly: bool, saveToFile: bool, inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
||||||
"""Creates a message
|
"""Creates a message
|
||||||
|
|
|
@ -7,12 +7,16 @@ __email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from requests_toolbelt.adapters.source import SourceAddressAdapter
|
||||||
import json
|
import json
|
||||||
|
|
||||||
baseDirectory=None
|
baseDirectory=None
|
||||||
|
|
||||||
def createSession(onionRoute: bool):
|
def createSession(domain: str, port: int, onionRoute: bool):
|
||||||
session = requests.session()
|
session = requests.session()
|
||||||
|
if domain.startswith('127.') or domain.startswith('192.') or domain.startswith('10.'):
|
||||||
|
session.mount('http://', SourceAddressAdapter(domain))
|
||||||
|
#session.mount('http://', SourceAddressAdapter((domain, port)))
|
||||||
if onionRoute:
|
if onionRoute:
|
||||||
session.proxies = {}
|
session.proxies = {}
|
||||||
session.proxies['http'] = 'socks5h://localhost:9050'
|
session.proxies['http'] = 'socks5h://localhost:9050'
|
||||||
|
|
16
tests.py
16
tests.py
|
@ -109,8 +109,8 @@ def createServerAlice(path: str,domain: str,port: int,federationList: []):
|
||||||
useTor=False
|
useTor=False
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,username,domain,port,https,True)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,username,domain,port,https,True)
|
||||||
deleteAllPosts(username,domain,path)
|
deleteAllPosts(username,domain,path)
|
||||||
followPerson(path,username,domain,'bob','127.0.10.2:61936',federationList)
|
followPerson(path,username,domain,'bob','127.0.0.100:61936',federationList)
|
||||||
followerOfPerson(path,username,domain,'bob','127.0.10.2:61936',federationList)
|
followerOfPerson(path,username,domain,'bob','127.0.0.100:61936',federationList)
|
||||||
createPublicPost(path,username, domain, port,https, "No wise fish would go anywhere without a porpoise", False, True)
|
createPublicPost(path,username, domain, port,https, "No wise fish would go anywhere without a porpoise", False, True)
|
||||||
createPublicPost(path,username, domain, port,https, "Curiouser and curiouser!", False, True)
|
createPublicPost(path,username, domain, port,https, "Curiouser and curiouser!", False, True)
|
||||||
createPublicPost(path,username, domain, port,https, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True)
|
createPublicPost(path,username, domain, port,https, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True)
|
||||||
|
@ -130,8 +130,8 @@ def createServerBob(path: str,domain: str,port: int,federationList: []):
|
||||||
useTor=False
|
useTor=False
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,username,domain,port,https,True)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,username,domain,port,https,True)
|
||||||
deleteAllPosts(username,domain,path)
|
deleteAllPosts(username,domain,path)
|
||||||
followPerson(path,username,domain,'alice','127.0.10.1:61935',federationList)
|
followPerson(path,username,domain,'alice','127.0.0.50:61935',federationList)
|
||||||
followerOfPerson(path,username,domain,'alice','127.0.10.1:61935',federationList)
|
followerOfPerson(path,username,domain,'alice','127.0.0.50:61935',federationList)
|
||||||
createPublicPost(path,username, domain, port,https, "It's your life, live it your way.", False, True)
|
createPublicPost(path,username, domain, port,https, "It's your life, live it your way.", False, True)
|
||||||
createPublicPost(path,username, domain, port,https, "One of the things I've realised is that I am very simple", False, True)
|
createPublicPost(path,username, domain, port,https, "One of the things I've realised is that I am very simple", False, True)
|
||||||
createPublicPost(path,username, domain, port,https, "Quantum physics is a bit of a passion of mine", False, True)
|
createPublicPost(path,username, domain, port,https, "Quantum physics is a bit of a passion of mine", False, True)
|
||||||
|
@ -150,7 +150,7 @@ def testPostMessageBetweenServers():
|
||||||
|
|
||||||
https=False
|
https=False
|
||||||
useTor=False
|
useTor=False
|
||||||
federationList=['127.0.0.1','127.0.10.1','127.0.10.2']
|
federationList=['127.0.0.50','127.0.0.100']
|
||||||
|
|
||||||
baseDir=os.getcwd()
|
baseDir=os.getcwd()
|
||||||
if not os.path.isdir(baseDir+'/.tests'):
|
if not os.path.isdir(baseDir+'/.tests'):
|
||||||
|
@ -158,12 +158,12 @@ def testPostMessageBetweenServers():
|
||||||
|
|
||||||
# create the servers
|
# create the servers
|
||||||
aliceDir=baseDir+'/.tests/alice'
|
aliceDir=baseDir+'/.tests/alice'
|
||||||
aliceDomain='127.0.10.1'
|
aliceDomain='127.0.0.50'
|
||||||
alicePort=61935
|
alicePort=61935
|
||||||
thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList),daemon=True)
|
thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList),daemon=True)
|
||||||
|
|
||||||
bobDir=baseDir+'/.tests/bob'
|
bobDir=baseDir+'/.tests/bob'
|
||||||
bobDomain='127.0.10.2'
|
bobDomain='127.0.0.100'
|
||||||
bobPort=61936
|
bobPort=61936
|
||||||
thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList),daemon=True)
|
thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList),daemon=True)
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ def testPostMessageBetweenServers():
|
||||||
|
|
||||||
print('Alice sends to Bob')
|
print('Alice sends to Bob')
|
||||||
os.chdir(aliceDir)
|
os.chdir(aliceDir)
|
||||||
sessionAlice = createSession(useTor)
|
sessionAlice = createSession(aliceDomain,alicePort,useTor)
|
||||||
inReplyTo=None
|
inReplyTo=None
|
||||||
inReplyToAtomUri=None
|
inReplyToAtomUri=None
|
||||||
subject=None
|
subject=None
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
__filename__ = "utils.py"
|
||||||
|
__author__ = "Bob Mottram"
|
||||||
|
__license__ = "AGPL3+"
|
||||||
|
__version__ = "0.0.1"
|
||||||
|
__maintainer__ = "Bob Mottram"
|
||||||
|
__email__ = "bob@freedombone.net"
|
||||||
|
__status__ = "Production"
|
||||||
|
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
def getStatusNumber() -> (str,str):
|
||||||
|
"""Returns the status number and published date
|
||||||
|
"""
|
||||||
|
currTime=datetime.datetime.utcnow()
|
||||||
|
daysSinceEpoch=(currTime - datetime.datetime(1970,1,1)).days
|
||||||
|
# status is the number of seconds since epoch
|
||||||
|
statusNumber=str(((daysSinceEpoch*24*60*60) + (currTime.hour*60*60) + (currTime.minute*60) + currTime.second)*1000000 + currTime.microsecond)
|
||||||
|
published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
conversationDate=currTime.strftime("%Y-%m-%d")
|
||||||
|
return statusNumber,published
|
||||||
|
|
||||||
|
def createOutboxDir(username: str,domain: str,baseDir: str) -> str:
|
||||||
|
"""Create an outbox for a person and returns the feed filename and directory
|
||||||
|
"""
|
||||||
|
handle=username.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
|
Loading…
Reference in New Issue