mirror of https://gitlab.com/bashrc2/epicyon
Move outbox function to its own module
parent
3abac14512
commit
8cf1a6266a
249
daemon.py
249
daemon.py
|
@ -169,6 +169,7 @@ from httpsig import verifyPostHeaders
|
|||
from theme import setTheme
|
||||
from schedule import runPostSchedule
|
||||
from schedule import runPostScheduleWatchdog
|
||||
from outbox import postMessageToOutbox
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
@ -184,254 +185,6 @@ followsPerPage=12
|
|||
# number of item shares per page
|
||||
sharesPerPage=12
|
||||
|
||||
def postMessageToOutbox(messageJson: {},postToNickname: str, \
|
||||
server,baseDir: str,httpPrefix: str, \
|
||||
domain: str,domainFull: str,port: int, \
|
||||
recentPostsCache: {},followersThreads: [], \
|
||||
federationList: [],sendThreads: [], \
|
||||
postLog: [],cachedWebfingers: {}, \
|
||||
personCache: {},allowDeletion: bool, \
|
||||
useTor: bool,version: str,debug: bool) -> bool:
|
||||
"""post is received by the outbox
|
||||
Client to server message post
|
||||
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
|
||||
"""
|
||||
if not messageJson.get('type'):
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox has no "type" parameter')
|
||||
return False
|
||||
if not messageJson.get('object') and messageJson.get('content'):
|
||||
if messageJson['type']!='Create':
|
||||
# https://www.w3.org/TR/activitypub/#object-without-create
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox - adding Create wrapper')
|
||||
messageJson= \
|
||||
outboxMessageCreateWrap(httpPrefix, \
|
||||
postToNickname, \
|
||||
domain,port, \
|
||||
messageJson)
|
||||
if messageJson['type']=='Create':
|
||||
if not (messageJson.get('id') and \
|
||||
messageJson.get('type') and \
|
||||
messageJson.get('actor') and \
|
||||
messageJson.get('object') and \
|
||||
messageJson.get('to')):
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox - Create does not have the required parameters')
|
||||
return False
|
||||
testDomain,testPort=getDomainFromActor(messageJson['actor'])
|
||||
if testPort:
|
||||
if testPort!=80 and testPort!=443:
|
||||
testDomain=testDomain+':'+str(testPort)
|
||||
if isBlockedDomain(baseDir,testDomain):
|
||||
if debug:
|
||||
print('DEBUG: domain is blocked: '+messageJson['actor'])
|
||||
return False
|
||||
# https://www.w3.org/TR/activitypub/#create-activity-outbox
|
||||
messageJson['object']['attributedTo']=messageJson['actor']
|
||||
if messageJson['object'].get('attachment'):
|
||||
attachmentIndex=0
|
||||
if messageJson['object']['attachment'][attachmentIndex].get('mediaType'):
|
||||
fileExtension='png'
|
||||
mediaTypeStr= \
|
||||
messageJson['object']['attachment'][attachmentIndex]['mediaType']
|
||||
if mediaTypeStr.endswith('jpeg'):
|
||||
fileExtension='jpg'
|
||||
elif mediaTypeStr.endswith('gif'):
|
||||
fileExtension='gif'
|
||||
elif mediaTypeStr.endswith('webp'):
|
||||
fileExtension='webp'
|
||||
elif mediaTypeStr.endswith('audio/mpeg'):
|
||||
fileExtension='mp3'
|
||||
elif mediaTypeStr.endswith('ogg'):
|
||||
fileExtension='ogg'
|
||||
elif mediaTypeStr.endswith('mp4'):
|
||||
fileExtension='mp4'
|
||||
elif mediaTypeStr.endswith('webm'):
|
||||
fileExtension='webm'
|
||||
elif mediaTypeStr.endswith('ogv'):
|
||||
fileExtension='ogv'
|
||||
mediaDir= \
|
||||
baseDir+'/accounts/'+ \
|
||||
postToNickname+'@'+domain
|
||||
uploadMediaFilename=mediaDir+'/upload.'+fileExtension
|
||||
if not os.path.isfile(uploadMediaFilename):
|
||||
del messageJson['object']['attachment']
|
||||
else:
|
||||
# generate a path for the uploaded image
|
||||
mPath=getMediaPath()
|
||||
mediaPath=mPath+'/'+createPassword(32)+'.'+fileExtension
|
||||
createMediaDirs(baseDir,mPath)
|
||||
mediaFilename=baseDir+'/'+mediaPath
|
||||
# move the uploaded image to its new path
|
||||
os.rename(uploadMediaFilename,mediaFilename)
|
||||
# change the url of the attachment
|
||||
messageJson['object']['attachment'][attachmentIndex]['url']= \
|
||||
httpPrefix+'://'+domainFull+ \
|
||||
'/'+mediaPath
|
||||
|
||||
permittedOutboxTypes=[
|
||||
'Create','Announce','Like','Follow','Undo', \
|
||||
'Update','Add','Remove','Block','Delete', \
|
||||
'Delegate','Skill','Bookmark'
|
||||
]
|
||||
if messageJson['type'] not in permittedOutboxTypes:
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox - '+messageJson['type']+ \
|
||||
' is not a permitted activity type')
|
||||
return False
|
||||
if messageJson.get('id'):
|
||||
postId=messageJson['id'].replace('/activity','').replace('/undo','')
|
||||
if debug:
|
||||
print('DEBUG: id attribute exists within POST to outbox')
|
||||
else:
|
||||
if debug:
|
||||
print('DEBUG: No id attribute within POST to outbox')
|
||||
postId=None
|
||||
if debug:
|
||||
print('DEBUG: savePostToBox')
|
||||
if messageJson['type']!='Upgrade':
|
||||
savedFilename= \
|
||||
savePostToBox(baseDir, \
|
||||
httpPrefix, \
|
||||
postId, \
|
||||
postToNickname, \
|
||||
domainFull,messageJson,'outbox')
|
||||
if messageJson['type']=='Create' or \
|
||||
messageJson['type']=='Question' or \
|
||||
messageJson['type']=='Note' or \
|
||||
messageJson['type']=='Announce':
|
||||
inboxUpdateIndex('outbox',baseDir, \
|
||||
postToNickname+'@'+domain, \
|
||||
savedFilename,debug)
|
||||
if outboxAnnounce(recentPostsCache, \
|
||||
baseDir,messageJson,debug):
|
||||
if debug:
|
||||
print('DEBUG: Updated announcements (shares) collection for the post associated with the Announce activity')
|
||||
if not server.session:
|
||||
if debug:
|
||||
print('DEBUG: creating new session for c2s')
|
||||
server.session= \
|
||||
createSession(useTor)
|
||||
if debug:
|
||||
print('DEBUG: sending c2s post to followers')
|
||||
# remove inactive threads
|
||||
inactiveFollowerThreads=[]
|
||||
for th in followersThreads:
|
||||
if not th.is_alive():
|
||||
inactiveFollowerThreads.append(th)
|
||||
for th in inactiveFollowerThreads:
|
||||
followersThreads.remove(th)
|
||||
if debug:
|
||||
print('DEBUG: '+str(len(followersThreads))+' followers threads active')
|
||||
# retain up to 20 threads
|
||||
if len(followersThreads)>20:
|
||||
# kill the thread if it is still alive
|
||||
if followersThreads[0].is_alive():
|
||||
followersThreads[0].kill()
|
||||
# remove it from the list
|
||||
followersThreads.pop(0)
|
||||
# create a thread to send the post to followers
|
||||
followersThread= \
|
||||
sendToFollowersThread(server.session, \
|
||||
baseDir, \
|
||||
postToNickname, \
|
||||
domain, \
|
||||
port, \
|
||||
httpPrefix, \
|
||||
federationList, \
|
||||
sendThreads, \
|
||||
postLog, \
|
||||
cachedWebfingers, \
|
||||
personCache, \
|
||||
messageJson,debug, \
|
||||
version)
|
||||
followersThreads.append(followersThread)
|
||||
if debug:
|
||||
print('DEBUG: handle any unfollow requests')
|
||||
outboxUndoFollow(baseDir,messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle delegation requests')
|
||||
outboxDelegate(baseDir,postToNickname,messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle skills changes requests')
|
||||
outboxSkills(baseDir,postToNickname,messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle availability changes requests')
|
||||
outboxAvailability(baseDir,postToNickname,messageJson,debug)
|
||||
|
||||
if debug:
|
||||
print('DEBUG: handle any like requests')
|
||||
outboxLike(recentPostsCache, \
|
||||
baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle any undo like requests')
|
||||
outboxUndoLike(baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
|
||||
if debug:
|
||||
print('DEBUG: handle any bookmark requests')
|
||||
outboxBookmark(recentPostsCache, \
|
||||
baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle any undo bookmark requests')
|
||||
outboxUndoBookmark(recentPostsCache, \
|
||||
baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
|
||||
if debug:
|
||||
print('DEBUG: handle delete requests')
|
||||
outboxDelete(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
messageJson,debug, \
|
||||
allowDeletion)
|
||||
if debug:
|
||||
print('DEBUG: handle block requests')
|
||||
outboxBlock(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle undo block requests')
|
||||
outboxUndoBlock(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle share uploads')
|
||||
outboxShareUpload(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle undo share uploads')
|
||||
outboxUndoShareUpload(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: sending c2s post to named addresses')
|
||||
print('c2s sender: '+postToNickname+'@'+ \
|
||||
domain+':'+str(port))
|
||||
sendToNamedAddresses(server.session,baseDir, \
|
||||
postToNickname,domain, \
|
||||
port, \
|
||||
httpPrefix, \
|
||||
federationList, \
|
||||
sendThreads, \
|
||||
postLog, \
|
||||
cachedWebfingers, \
|
||||
personCache, \
|
||||
messageJson,debug, \
|
||||
version)
|
||||
return True
|
||||
|
||||
def readFollowList(filename: str) -> None:
|
||||
"""Returns a list of ActivityPub addresses to follow
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
__filename__ = "outbox.py"
|
||||
__author__ = "Bob Mottram"
|
||||
__license__ = "AGPL3+"
|
||||
__version__ = "1.1.0"
|
||||
__maintainer__ = "Bob Mottram"
|
||||
__email__ = "bob@freedombone.net"
|
||||
__status__ = "Production"
|
||||
|
||||
import os
|
||||
import json
|
||||
from session import createSession
|
||||
from posts import outboxMessageCreateWrap
|
||||
from posts import savePostToBox
|
||||
from posts import sendToFollowersThread
|
||||
from posts import sendToNamedAddresses
|
||||
from utils import getDomainFromActor
|
||||
from blocking import isBlockedDomain
|
||||
from blocking import outboxBlock
|
||||
from blocking import outboxUndoBlock
|
||||
from media import getMediaPath
|
||||
from media import createMediaDirs
|
||||
from inbox import inboxUpdateIndex
|
||||
from announce import outboxAnnounce
|
||||
from follow import outboxUndoFollow
|
||||
from roles import outboxDelegate
|
||||
from skills import outboxSkills
|
||||
from availability import outboxAvailability
|
||||
from like import outboxLike
|
||||
from like import outboxUndoLike
|
||||
from bookmarks import outboxBookmark
|
||||
from bookmarks import outboxUndoBookmark
|
||||
from delete import outboxDelete
|
||||
from shares import outboxShareUpload
|
||||
from shares import outboxUndoShareUpload
|
||||
|
||||
def postMessageToOutbox(messageJson: {},postToNickname: str, \
|
||||
server,baseDir: str,httpPrefix: str, \
|
||||
domain: str,domainFull: str,port: int, \
|
||||
recentPostsCache: {},followersThreads: [], \
|
||||
federationList: [],sendThreads: [], \
|
||||
postLog: [],cachedWebfingers: {}, \
|
||||
personCache: {},allowDeletion: bool, \
|
||||
useTor: bool,version: str,debug: bool) -> bool:
|
||||
"""post is received by the outbox
|
||||
Client to server message post
|
||||
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
|
||||
"""
|
||||
if not messageJson.get('type'):
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox has no "type" parameter')
|
||||
return False
|
||||
if not messageJson.get('object') and messageJson.get('content'):
|
||||
if messageJson['type']!='Create':
|
||||
# https://www.w3.org/TR/activitypub/#object-without-create
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox - adding Create wrapper')
|
||||
messageJson= \
|
||||
outboxMessageCreateWrap(httpPrefix, \
|
||||
postToNickname, \
|
||||
domain,port, \
|
||||
messageJson)
|
||||
if messageJson['type']=='Create':
|
||||
if not (messageJson.get('id') and \
|
||||
messageJson.get('type') and \
|
||||
messageJson.get('actor') and \
|
||||
messageJson.get('object') and \
|
||||
messageJson.get('to')):
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox - Create does not have the required parameters')
|
||||
return False
|
||||
testDomain,testPort=getDomainFromActor(messageJson['actor'])
|
||||
if testPort:
|
||||
if testPort!=80 and testPort!=443:
|
||||
testDomain=testDomain+':'+str(testPort)
|
||||
if isBlockedDomain(baseDir,testDomain):
|
||||
if debug:
|
||||
print('DEBUG: domain is blocked: '+messageJson['actor'])
|
||||
return False
|
||||
# https://www.w3.org/TR/activitypub/#create-activity-outbox
|
||||
messageJson['object']['attributedTo']=messageJson['actor']
|
||||
if messageJson['object'].get('attachment'):
|
||||
attachmentIndex=0
|
||||
if messageJson['object']['attachment'][attachmentIndex].get('mediaType'):
|
||||
fileExtension='png'
|
||||
mediaTypeStr= \
|
||||
messageJson['object']['attachment'][attachmentIndex]['mediaType']
|
||||
if mediaTypeStr.endswith('jpeg'):
|
||||
fileExtension='jpg'
|
||||
elif mediaTypeStr.endswith('gif'):
|
||||
fileExtension='gif'
|
||||
elif mediaTypeStr.endswith('webp'):
|
||||
fileExtension='webp'
|
||||
elif mediaTypeStr.endswith('audio/mpeg'):
|
||||
fileExtension='mp3'
|
||||
elif mediaTypeStr.endswith('ogg'):
|
||||
fileExtension='ogg'
|
||||
elif mediaTypeStr.endswith('mp4'):
|
||||
fileExtension='mp4'
|
||||
elif mediaTypeStr.endswith('webm'):
|
||||
fileExtension='webm'
|
||||
elif mediaTypeStr.endswith('ogv'):
|
||||
fileExtension='ogv'
|
||||
mediaDir= \
|
||||
baseDir+'/accounts/'+ \
|
||||
postToNickname+'@'+domain
|
||||
uploadMediaFilename=mediaDir+'/upload.'+fileExtension
|
||||
if not os.path.isfile(uploadMediaFilename):
|
||||
del messageJson['object']['attachment']
|
||||
else:
|
||||
# generate a path for the uploaded image
|
||||
mPath=getMediaPath()
|
||||
mediaPath=mPath+'/'+createPassword(32)+'.'+fileExtension
|
||||
createMediaDirs(baseDir,mPath)
|
||||
mediaFilename=baseDir+'/'+mediaPath
|
||||
# move the uploaded image to its new path
|
||||
os.rename(uploadMediaFilename,mediaFilename)
|
||||
# change the url of the attachment
|
||||
messageJson['object']['attachment'][attachmentIndex]['url']= \
|
||||
httpPrefix+'://'+domainFull+'/'+mediaPath
|
||||
|
||||
permittedOutboxTypes=[
|
||||
'Create','Announce','Like','Follow','Undo', \
|
||||
'Update','Add','Remove','Block','Delete', \
|
||||
'Delegate','Skill','Bookmark'
|
||||
]
|
||||
if messageJson['type'] not in permittedOutboxTypes:
|
||||
if debug:
|
||||
print('DEBUG: POST to outbox - '+messageJson['type']+ \
|
||||
' is not a permitted activity type')
|
||||
return False
|
||||
if messageJson.get('id'):
|
||||
postId=messageJson['id'].replace('/activity','').replace('/undo','')
|
||||
if debug:
|
||||
print('DEBUG: id attribute exists within POST to outbox')
|
||||
else:
|
||||
if debug:
|
||||
print('DEBUG: No id attribute within POST to outbox')
|
||||
postId=None
|
||||
if debug:
|
||||
print('DEBUG: savePostToBox')
|
||||
if messageJson['type']!='Upgrade':
|
||||
savedFilename= \
|
||||
savePostToBox(baseDir, \
|
||||
httpPrefix, \
|
||||
postId, \
|
||||
postToNickname, \
|
||||
domainFull,messageJson,'outbox')
|
||||
if messageJson['type']=='Create' or \
|
||||
messageJson['type']=='Question' or \
|
||||
messageJson['type']=='Note' or \
|
||||
messageJson['type']=='Announce':
|
||||
inboxUpdateIndex('outbox',baseDir, \
|
||||
postToNickname+'@'+domain, \
|
||||
savedFilename,debug)
|
||||
if outboxAnnounce(recentPostsCache, \
|
||||
baseDir,messageJson,debug):
|
||||
if debug:
|
||||
print('DEBUG: Updated announcements (shares) collection for the post associated with the Announce activity')
|
||||
if not server.session:
|
||||
if debug:
|
||||
print('DEBUG: creating new session for c2s')
|
||||
server.session= \
|
||||
createSession(useTor)
|
||||
if debug:
|
||||
print('DEBUG: sending c2s post to followers')
|
||||
# remove inactive threads
|
||||
inactiveFollowerThreads=[]
|
||||
for th in followersThreads:
|
||||
if not th.is_alive():
|
||||
inactiveFollowerThreads.append(th)
|
||||
for th in inactiveFollowerThreads:
|
||||
followersThreads.remove(th)
|
||||
if debug:
|
||||
print('DEBUG: '+str(len(followersThreads))+' followers threads active')
|
||||
# retain up to 20 threads
|
||||
if len(followersThreads)>20:
|
||||
# kill the thread if it is still alive
|
||||
if followersThreads[0].is_alive():
|
||||
followersThreads[0].kill()
|
||||
# remove it from the list
|
||||
followersThreads.pop(0)
|
||||
# create a thread to send the post to followers
|
||||
followersThread= \
|
||||
sendToFollowersThread(server.session, \
|
||||
baseDir, \
|
||||
postToNickname, \
|
||||
domain, \
|
||||
port, \
|
||||
httpPrefix, \
|
||||
federationList, \
|
||||
sendThreads, \
|
||||
postLog, \
|
||||
cachedWebfingers, \
|
||||
personCache, \
|
||||
messageJson,debug, \
|
||||
version)
|
||||
followersThreads.append(followersThread)
|
||||
if debug:
|
||||
print('DEBUG: handle any unfollow requests')
|
||||
outboxUndoFollow(baseDir,messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle delegation requests')
|
||||
outboxDelegate(baseDir,postToNickname,messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle skills changes requests')
|
||||
outboxSkills(baseDir,postToNickname,messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle availability changes requests')
|
||||
outboxAvailability(baseDir,postToNickname,messageJson,debug)
|
||||
|
||||
if debug:
|
||||
print('DEBUG: handle any like requests')
|
||||
outboxLike(recentPostsCache, \
|
||||
baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle any undo like requests')
|
||||
outboxUndoLike(baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
|
||||
if debug:
|
||||
print('DEBUG: handle any bookmark requests')
|
||||
outboxBookmark(recentPostsCache, \
|
||||
baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle any undo bookmark requests')
|
||||
outboxUndoBookmark(recentPostsCache, \
|
||||
baseDir,httpPrefix, \
|
||||
postToNickname,domain,port, \
|
||||
messageJson,debug)
|
||||
|
||||
if debug:
|
||||
print('DEBUG: handle delete requests')
|
||||
outboxDelete(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
messageJson,debug, \
|
||||
allowDeletion)
|
||||
if debug:
|
||||
print('DEBUG: handle block requests')
|
||||
outboxBlock(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle undo block requests')
|
||||
outboxUndoBlock(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle share uploads')
|
||||
outboxShareUpload(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: handle undo share uploads')
|
||||
outboxUndoShareUpload(baseDir,httpPrefix, \
|
||||
postToNickname,domain, \
|
||||
port,
|
||||
messageJson,debug)
|
||||
if debug:
|
||||
print('DEBUG: sending c2s post to named addresses')
|
||||
print('c2s sender: '+postToNickname+'@'+ \
|
||||
domain+':'+str(port))
|
||||
sendToNamedAddresses(server.session,baseDir, \
|
||||
postToNickname,domain, \
|
||||
port, \
|
||||
httpPrefix, \
|
||||
federationList, \
|
||||
sendThreads, \
|
||||
postLog, \
|
||||
cachedWebfingers, \
|
||||
personCache, \
|
||||
messageJson,debug, \
|
||||
version)
|
||||
return True
|
Loading…
Reference in New Issue