mirror of https://gitlab.com/bashrc2/epicyon
Option to use dat urls
parent
0f5592452a
commit
86aaff3c84
|
@ -12,7 +12,7 @@ from utils import getStatusNumber
|
||||||
from utils import createOutboxDir
|
from utils import createOutboxDir
|
||||||
from utils import urlPermitted
|
from utils import urlPermitted
|
||||||
|
|
||||||
def createAcceptReject(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,https: bool,objectUrl: str,acceptType: str) -> {}:
|
def createAcceptReject(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str,acceptType: str) -> {}:
|
||||||
"""Accepts or rejects something (eg. a follow request)
|
"""Accepts or rejects something (eg. a follow request)
|
||||||
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
|
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
|
and ccUrl might be a specific person favorited or repeated and the followers url
|
||||||
|
@ -21,16 +21,12 @@ def createAcceptReject(baseDir: str,federationList: [],nickname: str,domain: str
|
||||||
if not urlPermitted(objectUrl,federationList):
|
if not urlPermitted(objectUrl,federationList):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
newAccept = {
|
newAccept = {
|
||||||
'type': acceptType,
|
'type': acceptType,
|
||||||
'actor': prefix+'://'+domain+'/users/'+nickname,
|
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': [],
|
'cc': [],
|
||||||
'object': objectUrl
|
'object': objectUrl
|
||||||
|
@ -40,8 +36,8 @@ def createAcceptReject(baseDir: str,federationList: [],nickname: str,domain: str
|
||||||
newAccept['cc']=ccUrl
|
newAccept['cc']=ccUrl
|
||||||
return newAccept
|
return newAccept
|
||||||
|
|
||||||
def createAccept(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,https: bool,objectUrl: str) -> {}:
|
def createAccept(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str) -> {}:
|
||||||
return createAcceptReject(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,https,objectUrl,'Accept')
|
return createAcceptReject(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,'Accept')
|
||||||
|
|
||||||
def createReject(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,https: bool,objectUrl: str) -> {}:
|
def createReject(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str) -> {}:
|
||||||
return createAcceptReject(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,https,objectUrl,'Reject')
|
return createAcceptReject(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,'Reject')
|
||||||
|
|
34
announce.py
34
announce.py
|
@ -14,7 +14,7 @@ from utils import urlPermitted
|
||||||
|
|
||||||
def createAnnounce(baseDir: str,federationList: [], \
|
def createAnnounce(baseDir: str,federationList: [], \
|
||||||
nickname: str, domain: str, port: int, \
|
nickname: str, domain: str, port: int, \
|
||||||
toUrl: str, ccUrl: str, https: bool, \
|
toUrl: str, ccUrl: str, httpPrefix: str, \
|
||||||
objectUrl: str, saveToFile: bool) -> {}:
|
objectUrl: str, saveToFile: bool) -> {}:
|
||||||
"""Creates an announce message
|
"""Creates an announce message
|
||||||
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
|
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
|
||||||
|
@ -24,18 +24,14 @@ def createAnnounce(baseDir: str,federationList: [], \
|
||||||
if not urlPermitted(objectUrl,federationList):
|
if not urlPermitted(objectUrl,federationList):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
statusNumber,published = getStatusNumber()
|
statusNumber,published = getStatusNumber()
|
||||||
newAnnounceId=prefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber
|
newAnnounceId=httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber
|
||||||
newAnnounce = {
|
newAnnounce = {
|
||||||
'actor': prefix+'://'+domain+'/users/'+nickname,
|
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'atomUri': prefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
|
'atomUri': httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
|
||||||
'cc': [],
|
'cc': [],
|
||||||
'id': newAnnounceId+'/activity',
|
'id': newAnnounceId+'/activity',
|
||||||
'object': objectUrl,
|
'object': objectUrl,
|
||||||
|
@ -56,40 +52,32 @@ def createAnnounce(baseDir: str,federationList: [], \
|
||||||
return newAnnounce
|
return newAnnounce
|
||||||
|
|
||||||
def announcePublic(baseDir: str,federationList: [], \
|
def announcePublic(baseDir: str,federationList: [], \
|
||||||
nickname: str, domain: str, port: int, https: bool, \
|
nickname: str, domain: str, port: int, httpPrefix: str, \
|
||||||
objectUrl: str, saveToFile: bool) -> {}:
|
objectUrl: str, saveToFile: bool) -> {}:
|
||||||
"""Makes a public announcement
|
"""Makes a public announcement
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
fromDomain=domain
|
fromDomain=domain
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
fromDomain=fromDomain+':'+str(port)
|
fromDomain=fromDomain+':'+str(port)
|
||||||
|
|
||||||
toUrl = 'https://www.w3.org/ns/activitystreams#Public'
|
toUrl = 'https://www.w3.org/ns/activitystreams#Public'
|
||||||
ccUrl = prefix + '://'+fromDomain+'/users/'+nickname+'/followers'
|
ccUrl = httpPrefix + '://'+fromDomain+'/users/'+nickname+'/followers'
|
||||||
return createAnnounce(baseDir,nickname, domain, port, \
|
return createAnnounce(baseDir,nickname, domain, port, \
|
||||||
toUrl, ccUrl, https, objectUrl, saveToFile)
|
toUrl, ccUrl, httpPrefix, objectUrl, saveToFile)
|
||||||
|
|
||||||
def repeatPost(baseDir: str,federationList: [], \
|
def repeatPost(baseDir: str,federationList: [], \
|
||||||
nickname: str, domain: str, port: int, https: bool, \
|
nickname: str, domain: str, port: int, httpPrefix: str, \
|
||||||
announceNickname: str, announceDomain: str, \
|
announceNickname: str, announceDomain: str, \
|
||||||
announcePort: int, announceHttps: bool, \
|
announcePort: int, announceHttpsPrefix: str, \
|
||||||
announceStatusNumber: int, saveToFile: bool) -> {}:
|
announceStatusNumber: int, saveToFile: bool) -> {}:
|
||||||
"""Repeats a given status post
|
"""Repeats a given status post
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not announceHttps:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
announcedDomain=announceDomain
|
announcedDomain=announceDomain
|
||||||
if announcePort!=80 and announcePort!=443:
|
if announcePort!=80 and announcePort!=443:
|
||||||
announcedDomain=announcedDomain+':'+str(announcePort)
|
announcedDomain=announcedDomain+':'+str(announcePort)
|
||||||
|
|
||||||
objectUrl = prefix + '://'+announcedDomain+'/users/'+ \
|
objectUrl = announceHttpsPrefix + '://'+announcedDomain+'/users/'+ \
|
||||||
announceNickname+'/statuses/'+str(announceStatusNumber)
|
announceNickname+'/statuses/'+str(announceStatusNumber)
|
||||||
|
|
||||||
return announcePublic(baseDir,nickname, domain, port, https, objectUrl, saveToFile)
|
return announcePublic(baseDir,nickname, domain, port, httpPrefix, objectUrl, saveToFile)
|
||||||
|
|
||||||
|
|
12
daemon.py
12
daemon.py
|
@ -129,7 +129,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
# get outbox feed for a person
|
# get outbox feed for a person
|
||||||
outboxFeed=personOutboxJson(self.server.baseDir,self.server.domain, \
|
outboxFeed=personOutboxJson(self.server.baseDir,self.server.domain, \
|
||||||
self.server.port,self.path, \
|
self.server.port,self.path, \
|
||||||
self.server.https,maxPostsInFeed)
|
self.server.httpPrefix,maxPostsInFeed)
|
||||||
if outboxFeed:
|
if outboxFeed:
|
||||||
self._set_headers('application/json')
|
self._set_headers('application/json')
|
||||||
self.wfile.write(json.dumps(outboxFeed).encode('utf-8'))
|
self.wfile.write(json.dumps(outboxFeed).encode('utf-8'))
|
||||||
|
@ -137,7 +137,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
following=getFollowingFeed(self.server.baseDir,self.server.domain, \
|
following=getFollowingFeed(self.server.baseDir,self.server.domain, \
|
||||||
self.server.port,self.path, \
|
self.server.port,self.path, \
|
||||||
self.server.https,followsPerPage)
|
self.server.httpPrefix,followsPerPage)
|
||||||
if following:
|
if following:
|
||||||
self._set_headers('application/json')
|
self._set_headers('application/json')
|
||||||
self.wfile.write(json.dumps(following).encode('utf-8'))
|
self.wfile.write(json.dumps(following).encode('utf-8'))
|
||||||
|
@ -145,7 +145,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
return
|
return
|
||||||
followers=getFollowingFeed(self.server.baseDir,self.server.domain, \
|
followers=getFollowingFeed(self.server.baseDir,self.server.domain, \
|
||||||
self.server.port,self.path, \
|
self.server.port,self.path, \
|
||||||
self.server.https,followsPerPage,'followers')
|
self.server.httpPrefix,followsPerPage,'followers')
|
||||||
if followers:
|
if followers:
|
||||||
self._set_headers('application/json')
|
self._set_headers('application/json')
|
||||||
self.wfile.write(json.dumps(followers).encode('utf-8'))
|
self.wfile.write(json.dumps(followers).encode('utf-8'))
|
||||||
|
@ -305,7 +305,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if self.server.debug:
|
if self.server.debug:
|
||||||
print('DEBUG: POST check signature')
|
print('DEBUG: POST check signature')
|
||||||
|
|
||||||
if not verifyPostHeaders(self.server.https, pubKey, self.headers, \
|
if not verifyPostHeaders(self.server.httpPrefix, pubKey, self.headers, \
|
||||||
'/inbox' ,False, json.dumps(messageJson)):
|
'/inbox' ,False, json.dumps(messageJson)):
|
||||||
print('**************** POST signature verification failed')
|
print('**************** POST signature verification failed')
|
||||||
self.send_response(401)
|
self.send_response(401)
|
||||||
|
@ -336,7 +336,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.server.POSTbusy=False
|
self.server.POSTbusy=False
|
||||||
|
|
||||||
def runDaemon(domain: str,port=80,https=True,fedList=[],useTor=False,debug=False) -> None:
|
def runDaemon(domain: str,port=80,httpPrefix='https',fedList=[],useTor=False,debug=False) -> None:
|
||||||
if len(domain)==0:
|
if len(domain)==0:
|
||||||
domain='localhost'
|
domain='localhost'
|
||||||
if '.' not in domain:
|
if '.' not in domain:
|
||||||
|
@ -348,7 +348,7 @@ def runDaemon(domain: str,port=80,https=True,fedList=[],useTor=False,debug=False
|
||||||
httpd = ThreadingHTTPServer(serverAddress, PubServer)
|
httpd = ThreadingHTTPServer(serverAddress, PubServer)
|
||||||
httpd.domain=domain
|
httpd.domain=domain
|
||||||
httpd.port=port
|
httpd.port=port
|
||||||
httpd.https=https
|
httpd.httpPrefix=httpPrefix
|
||||||
httpd.debug=debug
|
httpd.debug=debug
|
||||||
httpd.federationList=fedList.copy()
|
httpd.federationList=fedList.copy()
|
||||||
httpd.baseDir=os.getcwd()
|
httpd.baseDir=os.getcwd()
|
||||||
|
|
13
epicyon.py
13
epicyon.py
|
@ -67,6 +67,9 @@ parser.add_argument("--debug", type=str2bool, nargs='?',
|
||||||
parser.add_argument("--http", type=str2bool, nargs='?',
|
parser.add_argument("--http", type=str2bool, nargs='?',
|
||||||
const=True, default=False,
|
const=True, default=False,
|
||||||
help="Use http only")
|
help="Use http only")
|
||||||
|
parser.add_argument("--dat", type=str2bool, nargs='?',
|
||||||
|
const=True, default=False,
|
||||||
|
help="Use dat protocol only")
|
||||||
parser.add_argument("--tor", type=str2bool, nargs='?',
|
parser.add_argument("--tor", type=str2bool, nargs='?',
|
||||||
const=True, default=False,
|
const=True, default=False,
|
||||||
help="Route via Tor")
|
help="Route via Tor")
|
||||||
|
@ -110,9 +113,11 @@ if not args.domain:
|
||||||
nickname='admin'
|
nickname='admin'
|
||||||
domain=args.domain
|
domain=args.domain
|
||||||
port=args.port
|
port=args.port
|
||||||
https=True
|
httpPrefix='https'
|
||||||
if args.http:
|
if args.http:
|
||||||
https=False
|
httpPrefix='http'
|
||||||
|
if args.dat:
|
||||||
|
httpPrefix='dat'
|
||||||
useTor=args.tor
|
useTor=args.tor
|
||||||
baseDir=args.baseDir
|
baseDir=args.baseDir
|
||||||
if baseDir.endswith('/'):
|
if baseDir.endswith('/'):
|
||||||
|
@ -126,6 +131,6 @@ if args.federationList:
|
||||||
|
|
||||||
if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
|
if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
|
||||||
print('Creating default admin account '+nickname+'@'+domain)
|
print('Creating default admin account '+nickname+'@'+domain)
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,https,True)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,httpPrefix,True)
|
||||||
|
|
||||||
runDaemon(domain,port,https,federationList,useTor,debug)
|
runDaemon(domain,port,httpPrefix,federationList,useTor,debug)
|
||||||
|
|
40
follow.py
40
follow.py
|
@ -114,7 +114,7 @@ def getNoOfFollowers(baseDir: str,nickname: str,domain: str) -> int:
|
||||||
"""
|
"""
|
||||||
return getNoOfFollows(baseDir,nickname,domain,'followers.txt')
|
return getNoOfFollows(baseDir,nickname,domain,'followers.txt')
|
||||||
|
|
||||||
def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,https: bool, \
|
def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,httpPrefix: str, \
|
||||||
followsPerPage=12,followFile='following') -> {}:
|
followsPerPage=12,followFile='following') -> {}:
|
||||||
"""Returns the following and followers feeds from GET requests
|
"""Returns the following and followers feeds from GET requests
|
||||||
"""
|
"""
|
||||||
|
@ -147,18 +147,14 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,https: bool, \
|
||||||
if not validNickname(nickname):
|
if not validNickname(nickname):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
if headerOnly:
|
if headerOnly:
|
||||||
following = {
|
following = {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'first': prefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page=1',
|
'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page=1',
|
||||||
'id': prefix+'://'+domain+'/users/'+nickname+'/'+followFile,
|
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile,
|
||||||
'totalItems': getNoOfFollows(nickname,domain),
|
'totalItems': getNoOfFollows(nickname,domain),
|
||||||
'type': 'OrderedCollection'}
|
'type': 'OrderedCollection'}
|
||||||
return following
|
return following
|
||||||
|
@ -169,9 +165,9 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,https: bool, \
|
||||||
nextPageNumber=int(pageNumber+1)
|
nextPageNumber=int(pageNumber+1)
|
||||||
following = {
|
following = {
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'id': prefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(pageNumber),
|
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(pageNumber),
|
||||||
'orderedItems': [],
|
'orderedItems': [],
|
||||||
'partOf': prefix+'://'+domain+'/users/'+nickname+'/'+followFile,
|
'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile,
|
||||||
'totalItems': 0,
|
'totalItems': 0,
|
||||||
'type': 'OrderedCollectionPage'}
|
'type': 'OrderedCollectionPage'}
|
||||||
|
|
||||||
|
@ -190,10 +186,10 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,https: bool, \
|
||||||
pageCtr += 1
|
pageCtr += 1
|
||||||
totalCtr += 1
|
totalCtr += 1
|
||||||
if currPage==pageNumber:
|
if currPage==pageNumber:
|
||||||
url = prefix + '://' + line.lower().replace('\n','').split('@')[1] + \
|
url = httpPrefix + '://' + line.lower().replace('\n','').split('@')[1] + \
|
||||||
'/users/' + line.lower().replace('\n','').split('@')[0]
|
'/users/' + line.lower().replace('\n','').split('@')[0]
|
||||||
following['orderedItems'].append(url)
|
following['orderedItems'].append(url)
|
||||||
elif line.startswith('http') and '/users/' in line:
|
elif (line.startswith('http') or line.startswith('dat')) and '/users/' in line:
|
||||||
pageCtr += 1
|
pageCtr += 1
|
||||||
totalCtr += 1
|
totalCtr += 1
|
||||||
if currPage==pageNumber:
|
if currPage==pageNumber:
|
||||||
|
@ -206,7 +202,7 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,https: bool, \
|
||||||
if lastPage<1:
|
if lastPage<1:
|
||||||
lastPage=1
|
lastPage=1
|
||||||
if nextPageNumber>lastPage:
|
if nextPageNumber>lastPage:
|
||||||
following['next']=prefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(lastPage)
|
following['next']=httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(lastPage)
|
||||||
return following
|
return following
|
||||||
|
|
||||||
def receiveFollowRequest(baseDir: str,messageJson: {},federationList: []) -> bool:
|
def receiveFollowRequest(baseDir: str,messageJson: {},federationList: []) -> bool:
|
||||||
|
@ -216,7 +212,7 @@ def receiveFollowRequest(baseDir: str,messageJson: {},federationList: []) -> boo
|
||||||
return False
|
return False
|
||||||
if '/users/' not in messageJson['actor']:
|
if '/users/' not in messageJson['actor']:
|
||||||
return False
|
return False
|
||||||
domain=messageJson['actor'].split('/users/')[0].replace('https://','').replace('http://','')
|
domain=messageJson['actor'].split('/users/')[0].replace('https://','').replace('http://','').replace('dat://','')
|
||||||
if not domainPermitted(domain,federationList):
|
if not domainPermitted(domain,federationList):
|
||||||
return False
|
return False
|
||||||
nickname=messageJson['actor'].split('/users/')[1].replace('@','')
|
nickname=messageJson['actor'].split('/users/')[1].replace('@','')
|
||||||
|
@ -225,7 +221,7 @@ def receiveFollowRequest(baseDir: str,messageJson: {},federationList: []) -> boo
|
||||||
return False
|
return False
|
||||||
if '/users/' not in messageJson['object']:
|
if '/users/' not in messageJson['object']:
|
||||||
return False
|
return False
|
||||||
domainToFollow=messageJson['object'].split('/users/')[0].replace('https://','').replace('http://','')
|
domainToFollow=messageJson['object'].split('/users/')[0].replace('https://','').replace('http://','').replace('dat://','')
|
||||||
if not domainPermitted(domainToFollow,federationList):
|
if not domainPermitted(domainToFollow,federationList):
|
||||||
return False
|
return False
|
||||||
nicknameToFollow=messageJson['object'].split('/users/')[1].replace('@','')
|
nicknameToFollow=messageJson['object'].split('/users/')[1].replace('@','')
|
||||||
|
@ -235,22 +231,14 @@ def receiveFollowRequest(baseDir: str,messageJson: {},federationList: []) -> boo
|
||||||
return False
|
return False
|
||||||
return followerOfPerson(baseDir,nickname,domain,nicknameToFollow,domainToFollow,federationList)
|
return followerOfPerson(baseDir,nickname,domain,nicknameToFollow,domainToFollow,federationList)
|
||||||
|
|
||||||
def sendFollowRequest(baseDir: str,nickname: str,domain: str,port: int,https: bool, \
|
def sendFollowRequest(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
|
||||||
followNickname: str,followDomain: str,followPort: bool,followHttps: bool, \
|
followNickname: str,followDomain: str,followPort: bool,followHttpPrefix: str, \
|
||||||
federationList: []) -> {}:
|
federationList: []) -> {}:
|
||||||
"""Gets the json object for sending a follow request
|
"""Gets the json object for sending a follow request
|
||||||
"""
|
"""
|
||||||
if not domainPermitted(followDomain,federationList):
|
if not domainPermitted(followDomain,federationList):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
followPrefix='https'
|
|
||||||
if not followHttps:
|
|
||||||
followPrefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
|
@ -259,8 +247,8 @@ def sendFollowRequest(baseDir: str,nickname: str,domain: str,port: int,https: bo
|
||||||
|
|
||||||
newFollow = {
|
newFollow = {
|
||||||
'type': 'Follow',
|
'type': 'Follow',
|
||||||
'actor': prefix+'://'+domain+'/users/'+nickname,
|
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'object': followPrefix+'://'+followDomain+'/users/'+followNickname,
|
'object': followHttpPrefix+'://'+followDomain+'/users/'+followNickname,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': []
|
'cc': []
|
||||||
}
|
}
|
||||||
|
|
18
httpsig.py
18
httpsig.py
|
@ -17,18 +17,14 @@ import json
|
||||||
|
|
||||||
def signPostHeaders(privateKeyPem: str, nickname: str, domain: str, \
|
def signPostHeaders(privateKeyPem: str, nickname: str, domain: str, \
|
||||||
port: int,path: str, \
|
port: int,path: str, \
|
||||||
https: bool, messageBodyJson: {}) -> str:
|
httpPrefix: str, messageBodyJson: {}) -> str:
|
||||||
"""Returns a raw signature string that can be plugged into a header and
|
"""Returns a raw signature string that can be plugged into a header and
|
||||||
used to verify the authenticity of an HTTP transmission.
|
used to verify the authenticity of an HTTP transmission.
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
keyID = prefix+'://'+domain+'/users/'+nickname+'/main-key'
|
keyID = httpPrefix+'://'+domain+'/users/'+nickname+'/main-key'
|
||||||
if not messageBodyJson:
|
if not messageBodyJson:
|
||||||
headers = {'host': domain}
|
headers = {'host': domain}
|
||||||
else:
|
else:
|
||||||
|
@ -63,7 +59,7 @@ def signPostHeaders(privateKeyPem: str, nickname: str, domain: str, \
|
||||||
return signatureHeader
|
return signatureHeader
|
||||||
|
|
||||||
def createSignedHeader(privateKeyPem: str,nickname: str,domain: str,port: int, \
|
def createSignedHeader(privateKeyPem: str,nickname: str,domain: str,port: int, \
|
||||||
path: str,https: bool,withDigest: bool, \
|
path: str,httpPrefix: str,withDigest: bool, \
|
||||||
messageBodyJson: {}) -> {}:
|
messageBodyJson: {}) -> {}:
|
||||||
headerDomain=domain
|
headerDomain=domain
|
||||||
|
|
||||||
|
@ -79,12 +75,12 @@ def createSignedHeader(privateKeyPem: str,nickname: str,domain: str,port: int, \
|
||||||
headers = {'host': headerDomain, 'digest': f'SHA-256={bodyDigest}'}
|
headers = {'host': headerDomain, 'digest': f'SHA-256={bodyDigest}'}
|
||||||
path='/inbox'
|
path='/inbox'
|
||||||
signatureHeader = signPostHeaders(privateKeyPem, nickname, domain, port, \
|
signatureHeader = signPostHeaders(privateKeyPem, nickname, domain, port, \
|
||||||
path, https, None)
|
path, httpPrefix, None)
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
headers['Content-type'] = 'application/json'
|
headers['Content-type'] = 'application/json'
|
||||||
return headers
|
return headers
|
||||||
|
|
||||||
def verifyPostHeaders(https: bool, publicKeyPem: str, headers: dict, \
|
def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict, \
|
||||||
path: str, GETmethod: bool, \
|
path: str, GETmethod: bool, \
|
||||||
messageBodyJsonStr: str) -> bool:
|
messageBodyJsonStr: str) -> bool:
|
||||||
"""Returns true or false depending on if the key that we plugged in here
|
"""Returns true or false depending on if the key that we plugged in here
|
||||||
|
@ -100,10 +96,6 @@ def verifyPostHeaders(https: bool, publicKeyPem: str, headers: dict, \
|
||||||
else:
|
else:
|
||||||
method='POST'
|
method='POST'
|
||||||
|
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
publicKeyPem = RSA.import_key(publicKeyPem)
|
publicKeyPem = RSA.import_key(publicKeyPem)
|
||||||
# Build a dictionary of the signature values
|
# Build a dictionary of the signature values
|
||||||
signatureHeader = headers['signature']
|
signatureHeader = headers['signature']
|
||||||
|
|
18
like.py
18
like.py
|
@ -11,7 +11,7 @@ import commentjson
|
||||||
from utils import urlPermitted
|
from utils import urlPermitted
|
||||||
|
|
||||||
def like(baseDir: str,federationList: [],nickname: str,domain: str,port: int, \
|
def like(baseDir: str,federationList: [],nickname: str,domain: str,port: int, \
|
||||||
toUrl: str,ccUrl: str,https: bool,objectUrl: str,saveToFile: bool) -> {}:
|
toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str,saveToFile: bool) -> {}:
|
||||||
"""Creates a like
|
"""Creates a like
|
||||||
Typically toUrl will be a followers collection
|
Typically toUrl will be a followers collection
|
||||||
and ccUrl might be a specific person whose post was liked
|
and ccUrl might be a specific person whose post was liked
|
||||||
|
@ -20,16 +20,12 @@ def like(baseDir: str,federationList: [],nickname: str,domain: str,port: int, \
|
||||||
if not urlPermitted(objectUrl,federationList):
|
if not urlPermitted(objectUrl,federationList):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
newLike = {
|
newLike = {
|
||||||
'type': 'Like',
|
'type': 'Like',
|
||||||
'actor': prefix+'://'+domain+'/users/'+nickname,
|
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'object': objectUrl,
|
'object': objectUrl,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': []
|
'cc': []
|
||||||
|
@ -44,19 +40,15 @@ def like(baseDir: str,federationList: [],nickname: str,domain: str,port: int, \
|
||||||
return newLike
|
return newLike
|
||||||
|
|
||||||
def likePost(baseDir: str,federationList: [], \
|
def likePost(baseDir: str,federationList: [], \
|
||||||
nickname: str, domain: str, port: int, https: bool, \n
|
nickname: str, domain: str, port: int, httpPrefix: str, \n
|
||||||
likeNickname: str, likeDomain: str, likePort: int, likeHttps: bool, \n
|
likeNickname: str, likeDomain: str, likePort: int, likeHttps: bool, \n
|
||||||
likeStatusNumber: int,saveToFile: bool) -> {}:
|
likeStatusNumber: int,saveToFile: bool) -> {}:
|
||||||
"""Likes a given status post
|
"""Likes a given status post
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not likeHttps:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
likeDomain=likeDomain
|
likeDomain=likeDomain
|
||||||
if likePort!=80 and likePort!=443:
|
if likePort!=80 and likePort!=443:
|
||||||
likeDomain=likeDomain+':'+str(likePort)
|
likeDomain=likeDomain+':'+str(likePort)
|
||||||
|
|
||||||
objectUrl = prefix + '://'+likeDomain+'/users/'+likeNickname+'/statuses/'+str(likeStatusNumber)
|
objectUrl = httpPrefix + '://'+likeDomain+'/users/'+likeNickname+'/statuses/'+str(likeStatusNumber)
|
||||||
|
|
||||||
return like(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,https,objectUrl,saveToFile)
|
return like(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,saveToFile)
|
||||||
|
|
36
person.py
36
person.py
|
@ -22,16 +22,12 @@ def generateRSAKey() -> (str,str):
|
||||||
return privateKeyPem,publicKeyPem
|
return privateKeyPem,publicKeyPem
|
||||||
|
|
||||||
def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
|
def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
|
||||||
https: bool, saveToFile: bool) -> (str,str,{},{}):
|
httpPrefix: str, saveToFile: bool) -> (str,str,{},{}):
|
||||||
"""Returns the private key, public key, actor and webfinger endpoint
|
"""Returns the private key, public key, actor and webfinger endpoint
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
privateKeyPem,publicKeyPem=generateRSAKey()
|
privateKeyPem,publicKeyPem=generateRSAKey()
|
||||||
webfingerEndpoint= \
|
webfingerEndpoint= \
|
||||||
createWebfingerEndpoint(nickname,domain,port,https,publicKeyPem)
|
createWebfingerEndpoint(nickname,domain,port,httpPrefix,publicKeyPem)
|
||||||
if saveToFile:
|
if saveToFile:
|
||||||
storeWebfingerEndpoint(nickname,domain,baseDir,webfingerEndpoint)
|
storeWebfingerEndpoint(nickname,domain,baseDir,webfingerEndpoint)
|
||||||
|
|
||||||
|
@ -54,29 +50,29 @@ def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
|
||||||
'toot': 'http://joinmastodon.org/ns#',
|
'toot': 'http://joinmastodon.org/ns#',
|
||||||
'value': 'schema:value'}],
|
'value': 'schema:value'}],
|
||||||
'attachment': [],
|
'attachment': [],
|
||||||
'endpoints': {'sharedInbox': prefix+'://'+domain+'/inbox'},
|
'endpoints': {'sharedInbox': httpPrefix+'://'+domain+'/inbox'},
|
||||||
'featured': prefix+'://'+domain+'/users/'+nickname+'/collections/featured',
|
'featured': httpPrefix+'://'+domain+'/users/'+nickname+'/collections/featured',
|
||||||
'followers': prefix+'://'+domain+'/users/'+nickname+'/followers',
|
'followers': httpPrefix+'://'+domain+'/users/'+nickname+'/followers',
|
||||||
'following': prefix+'://'+domain+'/users/'+nickname+'/following',
|
'following': httpPrefix+'://'+domain+'/users/'+nickname+'/following',
|
||||||
'icon': {'mediaType': 'image/png',
|
'icon': {'mediaType': 'image/png',
|
||||||
'type': 'Image',
|
'type': 'Image',
|
||||||
'url': prefix+'://'+domain+'/users/'+nickname+'_icon.png'},
|
'url': httpPrefix+'://'+domain+'/users/'+nickname+'_icon.png'},
|
||||||
'id': prefix+'://'+domain+'/users/'+nickname,
|
'id': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'image': {'mediaType': 'image/png',
|
'image': {'mediaType': 'image/png',
|
||||||
'type': 'Image',
|
'type': 'Image',
|
||||||
'url': prefix+'://'+domain+'/users/'+nickname+'.png'},
|
'url': httpPrefix+'://'+domain+'/users/'+nickname+'.png'},
|
||||||
'inbox': prefix+'://'+domain+'/users/'+nickname+'/inbox',
|
'inbox': httpPrefix+'://'+domain+'/users/'+nickname+'/inbox',
|
||||||
'manuallyApprovesFollowers': False,
|
'manuallyApprovesFollowers': False,
|
||||||
'name': nickname,
|
'name': nickname,
|
||||||
'outbox': prefix+'://'+domain+'/users/'+nickname+'/outbox',
|
'outbox': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox',
|
||||||
'preferredUsername': ''+nickname,
|
'preferredUsername': ''+nickname,
|
||||||
'publicKey': {'id': prefix+'://'+domain+'/users/'+nickname+'/main-key',
|
'publicKey': {'id': httpPrefix+'://'+domain+'/users/'+nickname+'/main-key',
|
||||||
'owner': prefix+'://'+domain+'/users/'+nickname,
|
'owner': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'publicKeyPem': publicKeyPem,
|
'publicKeyPem': publicKeyPem,
|
||||||
'summary': '',
|
'summary': '',
|
||||||
'tag': [],
|
'tag': [],
|
||||||
'type': 'Person',
|
'type': 'Person',
|
||||||
'url': prefix+'://'+domain+'/@'+nickname}
|
'url': httpPrefix+'://'+domain+'/@'+nickname}
|
||||||
}
|
}
|
||||||
|
|
||||||
if saveToFile:
|
if saveToFile:
|
||||||
|
@ -170,7 +166,7 @@ def personLookup(domain: str,path: str,baseDir: str) -> {}:
|
||||||
return personJson
|
return personJson
|
||||||
|
|
||||||
def personOutboxJson(baseDir: str,domain: str,port: int,path: str, \
|
def personOutboxJson(baseDir: str,domain: str,port: int,path: str, \
|
||||||
https: bool,noOfItems: int) -> []:
|
httpPrefix: str,noOfItems: int) -> []:
|
||||||
"""Obtain the outbox feed for the given person
|
"""Obtain the outbox feed for the given person
|
||||||
"""
|
"""
|
||||||
if not '/outbox' in path:
|
if not '/outbox' in path:
|
||||||
|
@ -204,7 +200,7 @@ def personOutboxJson(baseDir: str,domain: str,port: int,path: str, \
|
||||||
return None
|
return None
|
||||||
if not validNickname(nickname):
|
if not validNickname(nickname):
|
||||||
return None
|
return None
|
||||||
return createOutbox(baseDir,nickname,domain,port,https, \
|
return createOutbox(baseDir,nickname,domain,port,httpPrefix, \
|
||||||
noOfItems,headerOnly,pageNumber)
|
noOfItems,headerOnly,pageNumber)
|
||||||
|
|
||||||
def setPreferredNickname(baseDir: str,nickname: str, domain: str, \
|
def setPreferredNickname(baseDir: str,nickname: str, domain: str, \
|
||||||
|
|
69
posts.py
69
posts.py
|
@ -250,15 +250,11 @@ def deleteAllPosts(baseDir: str,nickname: str, domain: str) -> None:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
toUrl: str, ccUrl: str, https: bool, content: str, \
|
toUrl: str, ccUrl: str, httpPrefix: str, content: str, \
|
||||||
followersOnly: bool, saveToFile: bool, clientToServer: bool, \
|
followersOnly: bool, saveToFile: bool, clientToServer: bool, \
|
||||||
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
||||||
"""Creates a message
|
"""Creates a message
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
|
@ -266,11 +262,11 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
conversationDate=published.split('T')[0]
|
conversationDate=published.split('T')[0]
|
||||||
conversationId=statusNumber
|
conversationId=statusNumber
|
||||||
postTo='https://www.w3.org/ns/activitystreams#Public'
|
postTo='https://www.w3.org/ns/activitystreams#Public'
|
||||||
postCC=prefix+'://'+domain+'/users/'+nickname+'/followers'
|
postCC=httpPrefix+'://'+domain+'/users/'+nickname+'/followers'
|
||||||
if followersOnly:
|
if followersOnly:
|
||||||
postTo=postCC
|
postTo=postCC
|
||||||
postCC=''
|
postCC=''
|
||||||
newPostId=prefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber
|
newPostId=httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber
|
||||||
sensitive=False
|
sensitive=False
|
||||||
summary=None
|
summary=None
|
||||||
if subject:
|
if subject:
|
||||||
|
@ -280,7 +276,7 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
newPost = {
|
newPost = {
|
||||||
'id': newPostId+'/activity',
|
'id': newPostId+'/activity',
|
||||||
'type': 'Create',
|
'type': 'Create',
|
||||||
'actor': prefix+'://'+domain+'/users/'+nickname,
|
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'published': published,
|
'published': published,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': [],
|
'cc': [],
|
||||||
|
@ -290,12 +286,12 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
'summary': summary,
|
'summary': summary,
|
||||||
'inReplyTo': inReplyTo,
|
'inReplyTo': inReplyTo,
|
||||||
'published': published,
|
'published': published,
|
||||||
'url': prefix+'://'+domain+'/@'+nickname+'/'+statusNumber,
|
'url': httpPrefix+'://'+domain+'/@'+nickname+'/'+statusNumber,
|
||||||
'attributedTo': prefix+'://'+domain+'/users/'+nickname,
|
'attributedTo': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': [],
|
'cc': [],
|
||||||
'sensitive': sensitive,
|
'sensitive': sensitive,
|
||||||
'atomUri': prefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
|
'atomUri': httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
|
||||||
'inReplyToAtomUri': inReplyToAtomUri,
|
'inReplyToAtomUri': inReplyToAtomUri,
|
||||||
'conversation': 'tag:'+domain+','+conversationDate+':objectId='+conversationId+':objectType=Conversation',
|
'conversation': 'tag:'+domain+','+conversationDate+':objectId='+conversationId+':objectType=Conversation',
|
||||||
'content': content,
|
'content': content,
|
||||||
|
@ -322,12 +318,12 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
'summary': summary,
|
'summary': summary,
|
||||||
'inReplyTo': inReplyTo,
|
'inReplyTo': inReplyTo,
|
||||||
'published': published,
|
'published': published,
|
||||||
'url': prefix+'://'+domain+'/@'+nickname+'/'+statusNumber,
|
'url': httpPrefix+'://'+domain+'/@'+nickname+'/'+statusNumber,
|
||||||
'attributedTo': prefix+'://'+domain+'/users/'+nickname,
|
'attributedTo': httpPrefix+'://'+domain+'/users/'+nickname,
|
||||||
'to': [toUrl],
|
'to': [toUrl],
|
||||||
'cc': [],
|
'cc': [],
|
||||||
'sensitive': sensitive,
|
'sensitive': sensitive,
|
||||||
'atomUri': prefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
|
'atomUri': httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
|
||||||
'inReplyToAtomUri': inReplyToAtomUri,
|
'inReplyToAtomUri': inReplyToAtomUri,
|
||||||
'conversation': 'tag:'+domain+','+conversationDate+':objectId='+conversationId+':objectType=Conversation',
|
'conversation': 'tag:'+domain+','+conversationDate+':objectId='+conversationId+':objectType=Conversation',
|
||||||
'content': content,
|
'content': content,
|
||||||
|
@ -352,19 +348,16 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
return newPost
|
return newPost
|
||||||
|
|
||||||
def createPublicPost(baseDir: str,
|
def createPublicPost(baseDir: str,
|
||||||
nickname: str, domain: str, port: int,https: bool, \
|
nickname: str, domain: str, port: int,httpPrefix: str, \
|
||||||
content: str, followersOnly: bool, saveToFile: bool,
|
content: str, followersOnly: bool, saveToFile: bool,
|
||||||
clientToServer: bool, \
|
clientToServer: bool, \
|
||||||
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
||||||
"""Public post to the outbox
|
"""Public post to the outbox
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
return createPostBase(baseDir,nickname, domain, port, \
|
return createPostBase(baseDir,nickname, domain, port, \
|
||||||
'https://www.w3.org/ns/activitystreams#Public', \
|
'https://www.w3.org/ns/activitystreams#Public', \
|
||||||
prefix+'://'+domain+'/users/'+nickname+'/followers', \
|
httpPrefix+'://'+domain+'/users/'+nickname+'/followers', \
|
||||||
https, content, followersOnly, saveToFile, clientToServer, \
|
httpPrefix, content, followersOnly, saveToFile, clientToServer, \
|
||||||
inReplyTo, inReplyToAtomUri, subject)
|
inReplyTo, inReplyToAtomUri, subject)
|
||||||
|
|
||||||
def threadSendPost(session,postJsonObject: {},federationList: [],inboxUrl: str, \
|
def threadSendPost(session,postJsonObject: {},federationList: [],inboxUrl: str, \
|
||||||
|
@ -394,25 +387,21 @@ def threadSendPost(session,postJsonObject: {},federationList: [],inboxUrl: str,
|
||||||
|
|
||||||
def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
|
def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
toNickname: str, toDomain: str, toPort: int, cc: str, \
|
toNickname: str, toDomain: str, toPort: int, cc: str, \
|
||||||
https: bool, content: str, followersOnly: bool, \
|
httpPrefix: str, content: str, followersOnly: bool, \
|
||||||
saveToFile: bool, clientToServer: bool, federationList: [], \
|
saveToFile: bool, clientToServer: bool, federationList: [], \
|
||||||
sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \
|
sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \
|
||||||
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> int:
|
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> int:
|
||||||
"""Post to another inbox
|
"""Post to another inbox
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
withDigest=True
|
withDigest=True
|
||||||
|
|
||||||
if toPort!=80 and toPort!=443:
|
if toPort!=80 and toPort!=443:
|
||||||
toDomain=toDomain+':'+str(toPort)
|
toDomain=toDomain+':'+str(toPort)
|
||||||
|
|
||||||
handle=prefix+'://'+toDomain+'/@'+toNickname
|
handle=httpPrefix+'://'+toDomain+'/@'+toNickname
|
||||||
|
|
||||||
# lookup the inbox for the To handle
|
# lookup the inbox for the To handle
|
||||||
wfRequest = webfingerHandle(session,handle,https,cachedWebfingers)
|
wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers)
|
||||||
if not wfRequest:
|
if not wfRequest:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -428,7 +417,7 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
|
|
||||||
postJsonObject = \
|
postJsonObject = \
|
||||||
createPostBase(baseDir,nickname,domain,port, \
|
createPostBase(baseDir,nickname,domain,port, \
|
||||||
toPersonId,cc,https,content, \
|
toPersonId,cc,httpPrefix,content, \
|
||||||
followersOnly,saveToFile,clientToServer, \
|
followersOnly,saveToFile,clientToServer, \
|
||||||
inReplyTo,inReplyToAtomUri, \
|
inReplyTo,inReplyToAtomUri, \
|
||||||
subject)
|
subject)
|
||||||
|
@ -446,7 +435,7 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
# construct the http header
|
# construct the http header
|
||||||
signatureHeaderJson = \
|
signatureHeaderJson = \
|
||||||
createSignedHeader(privateKeyPem, nickname, domain, port, \
|
createSignedHeader(privateKeyPem, nickname, domain, port, \
|
||||||
postPath, https, withDigest, postJsonObject)
|
postPath, httpPrefix, withDigest, postJsonObject)
|
||||||
|
|
||||||
# Keep the number of threads being used small
|
# Keep the number of threads being used small
|
||||||
while len(sendThreads)>10:
|
while len(sendThreads)>10:
|
||||||
|
@ -462,14 +451,10 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
|
||||||
thr.start()
|
thr.start()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def createOutbox(baseDir: str,nickname: str,domain: str,port: int,https: bool, \
|
def createOutbox(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
|
||||||
itemsPerPage: int,headerOnly: bool,pageNumber=None) -> {}:
|
itemsPerPage: int,headerOnly: bool,pageNumber=None) -> {}:
|
||||||
"""Constructs the outbox feed
|
"""Constructs the outbox feed
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
outboxDir = createOutboxDir(nickname,domain,baseDir)
|
outboxDir = createOutboxDir(nickname,domain,baseDir)
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
|
@ -482,16 +467,16 @@ def createOutbox(baseDir: str,nickname: str,domain: str,port: int,https: bool, \
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
outboxHeader = {'@context': 'https://www.w3.org/ns/activitystreams',
|
outboxHeader = {'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'first': prefix+'://'+domain+'/users/'+nickname+'/outbox?page=true',
|
'first': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox?page=true',
|
||||||
'id': prefix+'://'+domain+'/users/'+nickname+'/outbox',
|
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox',
|
||||||
'last': prefix+'://'+domain+'/users/'+nickname+'/outbox?page=true',
|
'last': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox?page=true',
|
||||||
'totalItems': 0,
|
'totalItems': 0,
|
||||||
'type': 'OrderedCollection'}
|
'type': 'OrderedCollection'}
|
||||||
outboxItems = {'@context': 'https://www.w3.org/ns/activitystreams',
|
outboxItems = {'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'id': prefix+'://'+domain+'/users/'+nickname+'/outbox'+pageStr,
|
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox'+pageStr,
|
||||||
'orderedItems': [
|
'orderedItems': [
|
||||||
],
|
],
|
||||||
'partOf': prefix+'://'+domain+'/users/'+nickname+'/outbox',
|
'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/outbox',
|
||||||
'type': 'OrderedCollectionPage'}
|
'type': 'OrderedCollectionPage'}
|
||||||
|
|
||||||
# counter for posts loop
|
# counter for posts loop
|
||||||
|
@ -513,7 +498,7 @@ def createOutbox(baseDir: str,nickname: str,domain: str,port: int,https: bool, \
|
||||||
if lastPage<1:
|
if lastPage<1:
|
||||||
lastPage=1
|
lastPage=1
|
||||||
outboxHeader['last']= \
|
outboxHeader['last']= \
|
||||||
prefix+'://'+domain+'/users/'+nickname+'/outbox?page='+str(lastPage)
|
httpPrefix+'://'+domain+'/users/'+nickname+'/outbox?page='+str(lastPage)
|
||||||
|
|
||||||
# Insert posts
|
# Insert posts
|
||||||
currPage=1
|
currPage=1
|
||||||
|
@ -524,7 +509,7 @@ def createOutbox(baseDir: str,nickname: str,domain: str,port: int,https: bool, \
|
||||||
# update the prev entry for the last message id
|
# update the prev entry for the last message id
|
||||||
postId = prevPostFilename.split('#statuses#')[1].replace('#activity','')
|
postId = prevPostFilename.split('#statuses#')[1].replace('#activity','')
|
||||||
outboxHeader['prev']= \
|
outboxHeader['prev']= \
|
||||||
prefix+'://'+domain+'/users/'+nickname+'/outbox?min_id='+postId+'&page=true'
|
httpPrefix+'://'+domain+'/users/'+nickname+'/outbox?min_id='+postId+'&page=true'
|
||||||
# get the full path of the post file
|
# get the full path of the post file
|
||||||
filePath = os.path.join(outboxDir, postFilename)
|
filePath = os.path.join(outboxDir, postFilename)
|
||||||
try:
|
try:
|
||||||
|
@ -542,7 +527,7 @@ def createOutbox(baseDir: str,nickname: str,domain: str,port: int,https: bool, \
|
||||||
if '/statuses/' in p['id']:
|
if '/statuses/' in p['id']:
|
||||||
postId = p['id'].split('/statuses/')[1].replace('/activity','')
|
postId = p['id'].split('/statuses/')[1].replace('/activity','')
|
||||||
outboxHeader['next']= \
|
outboxHeader['next']= \
|
||||||
prefix+'://'+domain+'/users/'+ \
|
httpPrefix+'://'+domain+'/users/'+ \
|
||||||
nickname+'/outbox?max_id='+ \
|
nickname+'/outbox?max_id='+ \
|
||||||
postId+'&page=true'
|
postId+'&page=true'
|
||||||
postsOnPageCtr += 1
|
postsOnPageCtr += 1
|
||||||
|
|
52
tests.py
52
tests.py
|
@ -43,10 +43,10 @@ def testHttpsigBase(withDigest):
|
||||||
print('testHttpsig(' + str(withDigest) + ')')
|
print('testHttpsig(' + str(withDigest) + ')')
|
||||||
nickname='socrates'
|
nickname='socrates'
|
||||||
domain='argumentative.social'
|
domain='argumentative.social'
|
||||||
https=True
|
httpPrefix='https'
|
||||||
port=5576
|
port=5576
|
||||||
baseDir=os.getcwd()
|
baseDir=os.getcwd()
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,https,False)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,httpPrefix,False)
|
||||||
messageBodyJsonStr = '{"a key": "a value", "another key": "A string"}'
|
messageBodyJsonStr = '{"a key": "a value", "another key": "A string"}'
|
||||||
|
|
||||||
headersDomain=domain
|
headersDomain=domain
|
||||||
|
@ -60,11 +60,11 @@ def testHttpsigBase(withDigest):
|
||||||
headers = {'host': headersDomain, 'digest': f'SHA-256={bodyDigest}'}
|
headers = {'host': headersDomain, 'digest': f'SHA-256={bodyDigest}'}
|
||||||
|
|
||||||
path='/inbox'
|
path='/inbox'
|
||||||
signatureHeader = signPostHeaders(privateKeyPem, nickname, domain, port, path, https, None)
|
signatureHeader = signPostHeaders(privateKeyPem, nickname, domain, port, path, httpPrefix, None)
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
assert verifyPostHeaders(https, publicKeyPem, headers, '/inbox' ,False, messageBodyJsonStr)
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/inbox' ,False, messageBodyJsonStr)
|
||||||
assert verifyPostHeaders(https, publicKeyPem, headers, '/parambulator/inbox', False , messageBodyJsonStr) == False
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/parambulator/inbox', False , messageBodyJsonStr) == False
|
||||||
assert verifyPostHeaders(https, publicKeyPem, headers, '/inbox', True, messageBodyJsonStr) == False
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/inbox', True, messageBodyJsonStr) == False
|
||||||
if not withDigest:
|
if not withDigest:
|
||||||
# fake domain
|
# fake domain
|
||||||
headers = {'host': 'bogon.domain'}
|
headers = {'host': 'bogon.domain'}
|
||||||
|
@ -74,7 +74,7 @@ def testHttpsigBase(withDigest):
|
||||||
bodyDigest = base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest())
|
bodyDigest = base64.b64encode(SHA256.new(messageBodyJsonStr.encode()).digest())
|
||||||
headers = {'host': domain, 'digest': f'SHA-256={bodyDigest}'}
|
headers = {'host': domain, 'digest': f'SHA-256={bodyDigest}'}
|
||||||
headers['signature'] = signatureHeader
|
headers['signature'] = signatureHeader
|
||||||
assert verifyPostHeaders(https, publicKeyPem, headers, '/inbox', True, messageBodyJsonStr) == False
|
assert verifyPostHeaders(httpPrefix, publicKeyPem, headers, '/inbox', True, messageBodyJsonStr) == False
|
||||||
|
|
||||||
def testHttpsig():
|
def testHttpsig():
|
||||||
testHttpsigBase(False)
|
testHttpsigBase(False)
|
||||||
|
@ -111,20 +111,20 @@ def createServerAlice(path: str,domain: str,port: int,federationList: []):
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
os.chdir(path)
|
os.chdir(path)
|
||||||
nickname='alice'
|
nickname='alice'
|
||||||
https=False
|
httpPrefix=False
|
||||||
useTor=False
|
useTor=False
|
||||||
clientToServer=False
|
clientToServer=False
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,https,True)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True)
|
||||||
deleteAllPosts(path,nickname,domain)
|
deleteAllPosts(path,nickname,domain)
|
||||||
followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList)
|
followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList)
|
||||||
followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList)
|
followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList)
|
||||||
createPublicPost(path,nickname, domain, port,https, "No wise fish would go anywhere without a porpoise", False, True, clientToServer)
|
createPublicPost(path,nickname, domain, port,httpPrefix, "No wise fish would go anywhere without a porpoise", False, True, clientToServer)
|
||||||
createPublicPost(path,nickname, domain, port,https, "Curiouser and curiouser!", False, True, clientToServer)
|
createPublicPost(path,nickname, domain, port,httpPrefix, "Curiouser and curiouser!", False, True, clientToServer)
|
||||||
createPublicPost(path,nickname, domain, port,https, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer)
|
createPublicPost(path,nickname, domain, port,httpPrefix, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer)
|
||||||
global testServerAliceRunning
|
global testServerAliceRunning
|
||||||
testServerAliceRunning = True
|
testServerAliceRunning = True
|
||||||
print('Server running: Alice')
|
print('Server running: Alice')
|
||||||
runDaemon(domain,port,https,federationList,useTor,True)
|
runDaemon(domain,port,httpPrefix,federationList,useTor,True)
|
||||||
|
|
||||||
def createServerBob(path: str,domain: str,port: int,federationList: []):
|
def createServerBob(path: str,domain: str,port: int,federationList: []):
|
||||||
print('Creating test server: Bob on port '+str(port))
|
print('Creating test server: Bob on port '+str(port))
|
||||||
|
@ -133,20 +133,20 @@ def createServerBob(path: str,domain: str,port: int,federationList: []):
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
os.chdir(path)
|
os.chdir(path)
|
||||||
nickname='bob'
|
nickname='bob'
|
||||||
https=False
|
httpPrefix='http'
|
||||||
useTor=False
|
useTor=False
|
||||||
clientToServer=False
|
clientToServer=False
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,https,True)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True)
|
||||||
deleteAllPosts(path,nickname,domain)
|
deleteAllPosts(path,nickname,domain)
|
||||||
followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList)
|
followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList)
|
||||||
followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList)
|
followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList)
|
||||||
createPublicPost(path,nickname, domain, port,https, "It's your life, live it your way.", False, True, clientToServer)
|
createPublicPost(path,nickname, domain, port,httpPrefix, "It's your life, live it your way.", False, True, clientToServer)
|
||||||
createPublicPost(path,nickname, domain, port,https, "One of the things I've realised is that I am very simple", False, True, clientToServer)
|
createPublicPost(path,nickname, domain, port,httpPrefix, "One of the things I've realised is that I am very simple", False, True, clientToServer)
|
||||||
createPublicPost(path,nickname, domain, port,https, "Quantum physics is a bit of a passion of mine", False, True, clientToServer)
|
createPublicPost(path,nickname, domain, port,httpPrefix, "Quantum physics is a bit of a passion of mine", False, True, clientToServer)
|
||||||
global testServerBobRunning
|
global testServerBobRunning
|
||||||
testServerBobRunning = True
|
testServerBobRunning = True
|
||||||
print('Server running: Bob')
|
print('Server running: Bob')
|
||||||
runDaemon(domain,port,https,federationList,useTor,True)
|
runDaemon(domain,port,httpPrefix,federationList,useTor,True)
|
||||||
|
|
||||||
def testPostMessageBetweenServers():
|
def testPostMessageBetweenServers():
|
||||||
print('Testing sending message from one server to the inbox of another')
|
print('Testing sending message from one server to the inbox of another')
|
||||||
|
@ -156,7 +156,7 @@ def testPostMessageBetweenServers():
|
||||||
testServerAliceRunning = False
|
testServerAliceRunning = False
|
||||||
testServerBobRunning = False
|
testServerBobRunning = False
|
||||||
|
|
||||||
https=False
|
httpPrefix='http'
|
||||||
useTor=False
|
useTor=False
|
||||||
federationList=['127.0.0.50','127.0.0.100']
|
federationList=['127.0.0.50','127.0.0.100']
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ def testPostMessageBetweenServers():
|
||||||
ccUrl=None
|
ccUrl=None
|
||||||
alicePersonCache={}
|
alicePersonCache={}
|
||||||
aliceCachedWebfingers={}
|
aliceCachedWebfingers={}
|
||||||
sendResult = sendPost(sessionAlice,aliceDir,'alice', aliceDomain, alicePort, 'bob', bobDomain, bobPort, ccUrl, https, 'Why is a mouse when it spins?', followersOnly, saveToFile, clientToServer, federationList, aliceSendThreads, alicePostLog, aliceCachedWebfingers,alicePersonCache,inReplyTo, inReplyToAtomUri, subject)
|
sendResult = sendPost(sessionAlice,aliceDir,'alice', aliceDomain, alicePort, 'bob', bobDomain, bobPort, ccUrl, httpPrefix, 'Why is a mouse when it spins?', followersOnly, saveToFile, clientToServer, federationList, aliceSendThreads, alicePostLog, aliceCachedWebfingers,alicePersonCache,inReplyTo, inReplyToAtomUri, subject)
|
||||||
print('sendResult: '+str(sendResult))
|
print('sendResult: '+str(sendResult))
|
||||||
|
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
|
@ -221,14 +221,14 @@ def testFollows():
|
||||||
nickname='test529'
|
nickname='test529'
|
||||||
domain='testdomain.com'
|
domain='testdomain.com'
|
||||||
port=80
|
port=80
|
||||||
https=True
|
httpPrefix='https'
|
||||||
federationList=['wild.com','mesh.com']
|
federationList=['wild.com','mesh.com']
|
||||||
baseDir=currDir+'/.tests_testfollows'
|
baseDir=currDir+'/.tests_testfollows'
|
||||||
if os.path.isdir(baseDir):
|
if os.path.isdir(baseDir):
|
||||||
shutil.rmtree(baseDir)
|
shutil.rmtree(baseDir)
|
||||||
os.mkdir(baseDir)
|
os.mkdir(baseDir)
|
||||||
os.chdir(baseDir)
|
os.chdir(baseDir)
|
||||||
createPerson(baseDir,nickname,domain,port,https,True)
|
createPerson(baseDir,nickname,domain,port,httpPrefix,True)
|
||||||
|
|
||||||
clearFollows(baseDir,nickname,domain)
|
clearFollows(baseDir,nickname,domain)
|
||||||
followPerson(baseDir,nickname,domain,'badger','wild.com',federationList)
|
followPerson(baseDir,nickname,domain,'badger','wild.com',federationList)
|
||||||
|
@ -280,7 +280,7 @@ def testCreatePerson():
|
||||||
nickname='test382'
|
nickname='test382'
|
||||||
domain='badgerdomain.com'
|
domain='badgerdomain.com'
|
||||||
port=80
|
port=80
|
||||||
https=True
|
httpPrefix='https'
|
||||||
clientToServer=False
|
clientToServer=False
|
||||||
baseDir=currDir+'/.tests_createperson'
|
baseDir=currDir+'/.tests_createperson'
|
||||||
if os.path.isdir(baseDir):
|
if os.path.isdir(baseDir):
|
||||||
|
@ -288,12 +288,12 @@ def testCreatePerson():
|
||||||
os.mkdir(baseDir)
|
os.mkdir(baseDir)
|
||||||
os.chdir(baseDir)
|
os.chdir(baseDir)
|
||||||
|
|
||||||
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,https,True)
|
privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(baseDir,nickname,domain,port,httpPrefix,True)
|
||||||
deleteAllPosts(baseDir,nickname,domain)
|
deleteAllPosts(baseDir,nickname,domain)
|
||||||
setPreferredNickname(baseDir,nickname,domain,'badger')
|
setPreferredNickname(baseDir,nickname,domain,'badger')
|
||||||
setBio(baseDir,nickname,domain,'Randomly roaming in your backyard')
|
setBio(baseDir,nickname,domain,'Randomly roaming in your backyard')
|
||||||
archivePosts(nickname,domain,baseDir,4)
|
archivePosts(nickname,domain,baseDir,4)
|
||||||
createPublicPost(baseDir,nickname, domain, port,https, "G'day world!", False, True, clientToServer, None, None, 'Not suitable for Vogons')
|
createPublicPost(baseDir,nickname, domain, port,httpPrefix, "G'day world!", False, True, clientToServer, None, None, 'Not suitable for Vogons')
|
||||||
|
|
||||||
os.chdir(currDir)
|
os.chdir(currDir)
|
||||||
shutil.rmtree(baseDir)
|
shutil.rmtree(baseDir)
|
||||||
|
|
31
webfinger.py
31
webfinger.py
|
@ -22,11 +22,11 @@ def parseHandle(handle: str) -> (str,str):
|
||||||
return None, None
|
return None, None
|
||||||
if '/@' in handle:
|
if '/@' in handle:
|
||||||
domain, nickname = \
|
domain, nickname = \
|
||||||
handle.replace('https://','').replace('http://','').split('/@')
|
handle.replace('https://','').replace('http://','').replace('dat://','').split('/@')
|
||||||
else:
|
else:
|
||||||
if '/users/' in handle:
|
if '/users/' in handle:
|
||||||
domain, nickname = \
|
domain, nickname = \
|
||||||
handle.replace('https://','').replace('http://','').split('/users/')
|
handle.replace('https://','').replace('http://','').replace('dat://','').split('/users/')
|
||||||
else:
|
else:
|
||||||
if '@' in handle:
|
if '@' in handle:
|
||||||
nickname, domain = handle.split('@')
|
nickname, domain = handle.split('@')
|
||||||
|
@ -36,7 +36,7 @@ def parseHandle(handle: str) -> (str,str):
|
||||||
return nickname, domain
|
return nickname, domain
|
||||||
|
|
||||||
|
|
||||||
def webfingerHandle(session,handle: str,https: bool,cachedWebfingers: {}) -> {}:
|
def webfingerHandle(session,handle: str,httpPrefix: str,cachedWebfingers: {}) -> {}:
|
||||||
nickname, domain = parseHandle(handle)
|
nickname, domain = parseHandle(handle)
|
||||||
if not nickname:
|
if not nickname:
|
||||||
return None
|
return None
|
||||||
|
@ -47,10 +47,7 @@ def webfingerHandle(session,handle: str,https: bool,cachedWebfingers: {}) -> {}:
|
||||||
wf=getWebfingerFromCache(nickname+'@'+wfDomain,cachedWebfingers)
|
wf=getWebfingerFromCache(nickname+'@'+wfDomain,cachedWebfingers)
|
||||||
if wf:
|
if wf:
|
||||||
return wf
|
return wf
|
||||||
prefix='https'
|
url = '{}://{}/.well-known/webfinger'.format(httpPrefix,domain)
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
url = '{}://{}/.well-known/webfinger'.format(prefix,domain)
|
|
||||||
par = {'resource': 'acct:{}'.format(nickname+'@'+wfDomain)}
|
par = {'resource': 'acct:{}'.format(nickname+'@'+wfDomain)}
|
||||||
hdr = {'Accept': 'application/jrd+json'}
|
hdr = {'Accept': 'application/jrd+json'}
|
||||||
#try:
|
#try:
|
||||||
|
@ -83,39 +80,35 @@ def storeWebfingerEndpoint(nickname: str,domain: str,baseDir: str, \
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def createWebfingerEndpoint(nickname: str,domain: str,port: int, \
|
def createWebfingerEndpoint(nickname: str,domain: str,port: int, \
|
||||||
https: bool,publicKeyPem) -> {}:
|
httpPrefix: str,publicKeyPem) -> {}:
|
||||||
"""Creates a webfinger endpoint for a user
|
"""Creates a webfinger endpoint for a user
|
||||||
"""
|
"""
|
||||||
prefix='https'
|
|
||||||
if not https:
|
|
||||||
prefix='http'
|
|
||||||
|
|
||||||
if port!=80 and port!=443:
|
if port!=80 and port!=443:
|
||||||
domain=domain+':'+str(port)
|
domain=domain+':'+str(port)
|
||||||
|
|
||||||
account = {
|
account = {
|
||||||
"aliases": [
|
"aliases": [
|
||||||
prefix+"://"+domain+"/@"+nickname,
|
httpPrefix+"://"+domain+"/@"+nickname,
|
||||||
prefix+"://"+domain+"/users/"+nickname
|
httpPrefix+"://"+domain+"/users/"+nickname
|
||||||
],
|
],
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"href": prefix+"://"+domain+"/@"+nickname,
|
"href": httpPrefix+"://"+domain+"/@"+nickname,
|
||||||
"rel": "http://webfinger.net/rel/profile-page",
|
"rel": "http://webfinger.net/rel/profile-page",
|
||||||
"type": "text/html"
|
"type": "text/html"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": prefix+"://"+domain+"/users/"+nickname+".atom",
|
"href": httpPrefix+"://"+domain+"/users/"+nickname+".atom",
|
||||||
"rel": "http://schemas.google.com/g/2010#updates-from",
|
"rel": "http://schemas.google.com/g/2010#updates-from",
|
||||||
"type": "application/atom+xml"
|
"type": "application/atom+xml"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": prefix+"://"+domain+"/users/"+nickname,
|
"href": httpPrefix+"://"+domain+"/users/"+nickname,
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"type": "application/activity+json"
|
"type": "application/activity+json"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"href": prefix+"://"+domain+"/api/salmon/1",
|
"href": httpPrefix+"://"+domain+"/api/salmon/1",
|
||||||
"rel": "salmon"
|
"rel": "salmon"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -124,7 +117,7 @@ def createWebfingerEndpoint(nickname: str,domain: str,port: int, \
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
"rel": "http://ostatus.org/schema/1.0/subscribe",
|
||||||
"template": prefix+"://"+domain+"/authorize_interaction?uri={uri}"
|
"template": httpPrefix+"://"+domain+"/authorize_interaction?uri={uri}"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"subject": "acct:"+nickname+"@"+domain
|
"subject": "acct:"+nickname+"@"+domain
|
||||||
|
|
Loading…
Reference in New Issue