master
Bob Mottram 2019-11-03 13:43:47 +00:00
parent a6dc579aca
commit fc2732a5ed
10 changed files with 587 additions and 273 deletions

View File

@ -58,9 +58,13 @@ def createAcceptReject(baseDir: str,federationList: [], \
def createAccept(baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {},acceptedCaps=["inbox:write","objects:read"]) -> {}:
objectJson: {}, \
acceptedCaps=["inbox:write","objects:read"]) -> {}:
# create capabilities accept
ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain,port,toUrl,True,acceptedCaps)
ocapNew= \
capabilitiesAccept(baseDir,httpPrefix, \
nickname,domain,port, \
toUrl,True,acceptedCaps)
return createAcceptReject(baseDir,federationList, \
nickname,domain,port, \
toUrl,ccUrl,httpPrefix, \
@ -126,7 +130,7 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
print('DEBUG: nickname not found in '+thisActor)
return
if acceptedPort:
if not '/'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname in thisActor:
if '/'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname not in thisActor:
if debug:
print('Port: '+str(acceptedPort))
print('Expected: /'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname)
@ -134,7 +138,7 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
print('DEBUG: unrecognized actor '+thisActor)
return
else:
if not '/'+acceptedDomain+'/users/'+nickname in thisActor:
if '/'+acceptedDomain+'/users/'+nickname not in thisActor:
if debug:
print('Expected: /'+acceptedDomain+'/users/'+nickname)
print('Actual: '+thisActor)

View File

@ -62,7 +62,8 @@ def outboxAnnounce(baseDir: str,messageJson: {},debug: bool) -> bool:
return True
return False
def undoAnnounceCollectionEntry(postFilename: str,actor: str,debug: bool) -> None:
def undoAnnounceCollectionEntry(postFilename: str,actor: str, \
debug: bool) -> None:
"""Undoes an announce for a particular actor by removing it from the "shares"
collection within a post. Note that the "shares" collection has no relation
to shared items in shares.py. It's shares of posts, not shares of physical objects.
@ -102,14 +103,15 @@ def undoAnnounceCollectionEntry(postFilename: str,actor: str,debug: bool) -> Non
print('DEBUG: shares (announcements) was removed from post')
del postJsonObject['object']['shares']
else:
postJsonObject['object']['shares']['totalItems']=len(postJsonObject['object']['shares']['items'])
postJsonObject['object']['shares']['totalItems']= \
len(postJsonObject['object']['shares']['items'])
with open(postFilename, 'w') as fp:
commentjson.dump(postJsonObject, fp, indent=4, sort_keys=True)
def updateAnnounceCollection(postFilename: str,actor: str,debug: bool) -> None:
"""Updates the announcements collection within a post
Confusingly this is known as "shares", but isn't the same as shared items within shares.py
It's shares of posts, not shares of physical objects.
Confusingly this is known as "shares", but isn't the same as shared
items within shares.py. It's shares of posts, not shares of physical objects.
"""
with open(postFilename, 'r') as fp:
postJsonObject=commentjson.load(fp)
@ -146,7 +148,8 @@ def updateAnnounceCollection(postFilename: str,actor: str,debug: bool) -> None:
'actor': actor
}
postJsonObject['object']['shares']['items'].append(newAnnounce)
postJsonObject['object']['shares']['totalItems']=len(postJsonObject['object']['shares']['items'])
postJsonObject['object']['shares']['totalItems']= \
len(postJsonObject['object']['shares']['items'])
else:
if debug:
print('DEBUG: shares (announcements) section of post has no items list')

View File

@ -46,7 +46,8 @@ def getAvailability(baseDir: str,nickname: str,domain: str) -> str:
return actorJson['availability']
return None
def outboxAvailability(baseDir: str,nickname: str,messageJson: {},debug: bool) -> bool:
def outboxAvailability(baseDir: str,nickname: str,messageJson: {}, \
debug: bool) -> bool:
"""Handles receiving an availability update
"""
if not messageJson.get('type'):

View File

@ -11,7 +11,8 @@ import time
import datetime
import commentjson
def storePersonInCache(baseDir: str,personUrl: str,personJson: {},personCache: {}) -> None:
def storePersonInCache(baseDir: str,personUrl: str, \
personJson: {},personCache: {}) -> None:
"""Store an actor in the cache
"""
currTime=datetime.datetime.utcnow()
@ -35,7 +36,8 @@ def getPersonFromCache(baseDir: str,personUrl: str,personCache: {}) -> {}:
# if the actor is not in memory then try to load it from file
loadedFromFile=False
if not personCache.get(personUrl):
cacheFilename=baseDir+'/cache/actors/'+personUrl.replace('/','#')+'.json'
cacheFilename= \
baseDir+'/cache/actors/'+personUrl.replace('/','#')+'.json'
if os.path.isfile(cacheFilename):
personJson=None
try:
@ -52,11 +54,12 @@ def getPersonFromCache(baseDir: str,personUrl: str,personCache: {}) -> {}:
if not loadedFromFile:
# update the timestamp for the last time the actor was retrieved
currTime=datetime.datetime.utcnow()
personCache[personUrl]['timestamp']=currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
personCache[personUrl]['timestamp']= \
currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
return personCache[personUrl]['actor']
return None
def expirePersonCache(personCache: {}):
def expirePersonCache(personCache: {}) -> None:
"""Expires old entries from the cache in memory
"""
currTime=datetime.datetime.utcnow()

View File

@ -15,7 +15,8 @@ from auth import createPassword
from utils import getNicknameFromActor
from utils import getDomainFromActor
def getOcapFilename(baseDir :str,nickname: str,domain: str,actor :str,subdir: str) -> str:
def getOcapFilename(baseDir :str,nickname: str,domain: str, \
actor :str,subdir: str) -> str:
"""Returns the filename for a particular capability accepted or granted
Also creates directories as needed
"""
@ -40,7 +41,8 @@ def getOcapFilename(baseDir :str,nickname: str,domain: str,actor :str,subdir: st
if not os.path.isdir(ocDir):
os.mkdir(ocDir)
return baseDir+'/accounts/'+nickname+'@'+domain+'/ocap/'+subdir+'/'+actor.replace('/','#')+'.json'
return baseDir+'/accounts/'+nickname+'@'+domain+'/ocap/'+ \
subdir+'/'+actor.replace('/','#')+'.json'
def CapablePost(postJson: {}, capabilityList: [], debug :bool) -> bool:
"""Determines whether a post arriving in the inbox
@ -120,7 +122,8 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str, \
fullDomain=domain+':'+str(port)
# make directories to store capabilities
ocapFilename=getOcapFilename(baseDir,nickname,fullDomain,acceptedActor,'accept')
ocapFilename= \
getOcapFilename(baseDir,nickname,fullDomain,acceptedActor,'accept')
if not ocapFilename:
return None
ocapAccept=None
@ -137,9 +140,11 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str, \
return None
acceptedActorDomain,acceptedActorPort=getDomainFromActor(acceptedActor)
if acceptedActorPort:
ocapId=acceptedActorNickname+'@'+acceptedActorDomain+':'+str(acceptedActorPort)+'#'+createPassword(32)
ocapId=acceptedActorNickname+'@'+acceptedActorDomain+':'+ \
str(acceptedActorPort)+'#'+createPassword(32)
else:
ocapId=acceptedActorNickname+'@'+acceptedActorDomain+'#'+createPassword(32)
ocapId=acceptedActorNickname+'@'+acceptedActorDomain+'#'+ \
createPassword(32)
ocapAccept = {
"@context": "https://www.w3.org/ns/activitystreams",
"id": httpPrefix+"://"+fullDomain+"/caps/"+ocapId,
@ -156,13 +161,15 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str, \
commentjson.dump(ocapAccept, fp, indent=4, sort_keys=False)
return ocapAccept
def capabilitiesGrantedSave(baseDir :str,nickname :str,domain :str,ocap: {}) -> bool:
def capabilitiesGrantedSave(baseDir :str, \
nickname :str,domain :str,ocap: {}) -> bool:
"""A capabilities accept is received, so stor it for
reference when sending to the actor
"""
if not ocap.get('actor'):
return False
ocapFilename=getOcapFilename(baseDir,nickname,domain,ocap['actor'],'granted')
ocapFilename= \
getOcapFilename(baseDir,nickname,domain,ocap['actor'],'granted')
if not ocapFilename:
return False
with open(ocapFilename, 'w') as fp:
@ -189,7 +196,8 @@ def capabilitiesUpdate(baseDir: str,httpPrefix: str, \
fullDomain=domain+':'+str(port)
# Get the filename of the capability
ocapFilename=getOcapFilename(baseDir,nickname,fullDomain,updateActor,'accept')
ocapFilename= \
getOcapFilename(baseDir,nickname,fullDomain,updateActor,'accept')
if not ocapFilename:
return None
@ -221,7 +229,8 @@ def capabilitiesUpdate(baseDir: str,httpPrefix: str, \
return None
updateActorDomain,updateActorPort=getDomainFromActor(updateActor)
if updateActorPort:
ocapId=updateActorNickname+'@'+updateActorDomain+':'+str(updateActorPort)+'#'+createPassword(32)
ocapId=updateActorNickname+'@'+updateActorDomain+':'+ \
str(updateActorPort)+'#'+createPassword(32)
else:
ocapId=updateActorNickname+'@'+updateActorDomain+'#'+createPassword(32)
ocapJson['id']=httpPrefix+"://"+fullDomain+"/caps/"+ocapId

View File

@ -32,7 +32,7 @@ def setConfigParam(baseDir: str, variableName: str, variableValue) -> None:
with open(configFilename, 'w') as fp:
commentjson.dump(configJson, fp, indent=4, sort_keys=True)
def getConfigParam(baseDir: str, variableName: str):
def getConfigParam(baseDir: str, variableName: str) -> None:
"""Gets a configuration value
"""
createConfig(baseDir)

View File

@ -30,13 +30,17 @@ def addMusicTag(content: str,tag: str) -> str:
def addWebLinks(content: str) -> str:
"""Adds markup for web links
"""
if not ('https://' in content or 'http://' in content or 'dat://' in content):
if not ('https://' in content or \
'http://' in content or \
'dat://' in content):
return content
words=content.replace('\n',' --linebreak--').split(' ')
replaceDict={}
for w in words:
if w.startswith('https://') or w.startswith('http://') or w.startswith('dat://'):
if w.startswith('https://') or \
w.startswith('http://') or \
w.startswith('dat://'):
if w.endswith('.') or w.endswith(';'):
w=w[:-1]
markup='<a href="'+w+'" rel="nofollow noopener" target="_blank">'
@ -46,7 +50,9 @@ def addWebLinks(content: str) -> str:
markup+='<span class="invisible">http://</span>'
elif w.startswith('dat://'):
markup+='<span class="invisible">dat://</span>'
markup+='<span class="ellipsis">'+w.replace('https://','').replace('http://','').replace('dat://','')+'</span></a>'
markup+='<span class="ellipsis">'+ \
w.replace('https://','').replace('http://','').replace('dat://','')+ \
'</span></a>'
replaceDict[w]=markup
for url,markup in replaceDict.items():
content=content.replace(url,markup)
@ -56,12 +62,15 @@ def addWebLinks(content: str) -> str:
def validHashTag(hashtag: str) -> bool:
"""Returns true if the give hashtag contains valid characters
"""
validChars = set('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
validChars = \
set('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
if set(hashtag).issubset(validChars):
return True
return False
def addHashTags(wordStr: str,httpPrefix: str,domain: str,replaceHashTags: {},postHashtags: {}) -> bool:
def addHashTags(wordStr: str, \
httpPrefix: str,domain: str, \
replaceHashTags: {},postHashtags: {}) -> bool:
"""Detects hashtags and adds them to the replacements dict
Also updates the hashtags list to be added to the post
"""
@ -81,7 +90,9 @@ def addHashTags(wordStr: str,httpPrefix: str,domain: str,replaceHashTags: {},pos
'type': 'Hashtag'
}
replaceHashTags[wordStr]= \
"<a href=\""+hashtagUrl+"\" class=\"mention hashtag\" rel=\"tag\">#<span>"+hashtag+"</span></a>"
"<a href=\""+hashtagUrl+ \
"\" class=\"mention hashtag\" rel=\"tag\">#<span>"+ \
hashtag+"</span></a>"
return True
def loadEmojiDict(emojiDataFilename: str,emojiDict: {}) -> None:
@ -104,12 +115,15 @@ def loadEmojiDict(emojiDataFilename: str,emojiDict: {}) -> None:
continue
if '..' in emojiUnicode:
emojiUnicode=emojiUnicode.split('..')[0]
emojiName=line.split(')',1)[1].strip().replace('\n','').replace(' ','').replace('-','')
emojiName= \
line.split(')',1)[1].strip().replace('\n','').replace(' ','').replace('-','')
if '..' in emojiName:
emojiName=emojiName.split('..')[0]
emojiDict[emojiName.lower()]=emojiUnicode
def addEmoji(baseDir: str,wordStr: str,httpPrefix: str,domain: str,replaceEmoji: {},postTags: {},emojiDict: {}) -> bool:
def addEmoji(baseDir: str,wordStr: str, \
httpPrefix: str,domain: str, \
replaceEmoji: {},postTags: {},emojiDict: {}) -> bool:
"""Detects Emoji and adds them to the replacements dict
Also updates the tags list to be added to the post
"""
@ -142,7 +156,9 @@ def addEmoji(baseDir: str,wordStr: str,httpPrefix: str,domain: str,replaceEmoji:
}
return True
def addMention(wordStr: str,httpPrefix: str,following: str,replaceMentions: {},recipients: [],tags: {}) -> bool:
def addMention(wordStr: str, \
httpPrefix: str,following: str, \
replaceMentions: {},recipients: [],tags: {}) -> bool:
"""Detects mentions and adds them to the replacements dict and recipients list
"""
if not wordStr.startswith('@'):
@ -158,7 +174,8 @@ def addMention(wordStr: str,httpPrefix: str,following: str,replaceMentions: {},r
for follow in following:
if follow.startswith(possibleNickname+'@'):
replaceDomain=follow.replace('\n','').split('@')[1]
recipientActor=httpPrefix+"://"+replaceDomain+"/users/"+possibleNickname
recipientActor= \
httpPrefix+"://"+replaceDomain+"/users/"+possibleNickname
if recipientActor not in recipients:
recipients.append(recipientActor)
tags[wordStr]={
@ -166,7 +183,11 @@ def addMention(wordStr: str,httpPrefix: str,following: str,replaceMentions: {},r
'name': wordStr,
'type': 'Mention'
}
replaceMentions[wordStr]="<span class=\"h-card\"><a href=\""+httpPrefix+"://"+replaceDomain+"/@"+possibleNickname+"\" class=\"u-url mention\">@<span>"+possibleNickname+"</span></a></span>"
replaceMentions[wordStr]= \
"<span class=\"h-card\"><a href=\""+httpPrefix+ \
"://"+replaceDomain+"/@"+possibleNickname+ \
"\" class=\"u-url mention\">@<span>"+ \
possibleNickname+"</span></a></span>"
return True
return False
possibleNickname=possibleHandle.split('@')[0]
@ -175,7 +196,8 @@ def addMention(wordStr: str,httpPrefix: str,following: str,replaceMentions: {},r
for follow in following:
if follow.replace('\n','')!=possibleHandle:
continue
recipientActor=httpPrefix+"://"+possibleDomain+"/users/"+possibleNickname
recipientActor= \
httpPrefix+"://"+possibleDomain+"/users/"+possibleNickname
if recipientActor not in recipients:
recipients.append(recipientActor)
tags[wordStr]={
@ -183,13 +205,18 @@ def addMention(wordStr: str,httpPrefix: str,following: str,replaceMentions: {},r
'name': wordStr,
'type': 'Mention'
}
replaceMentions[wordStr]="<span class=\"h-card\"><a href=\""+httpPrefix+"://"+possibleDomain+"/@"+possibleNickname+"\" class=\"u-url mention\">@<span>"+possibleNickname+"</span></a></span>"
replaceMentions[wordStr]= \
"<span class=\"h-card\"><a href=\""+httpPrefix+ \
"://"+possibleDomain+"/@"+possibleNickname+ \
"\" class=\"u-url mention\">@<span>"+possibleNickname+ \
"</span></a></span>"
return True
# @nick@domain
if '@' in possibleHandle:
if not (possibleDomain=='localhost' or '.' in possibleDomain):
return False
recipientActor=httpPrefix+"://"+possibleDomain+"/users/"+possibleNickname
recipientActor= \
httpPrefix+"://"+possibleDomain+"/users/"+possibleNickname
if recipientActor not in recipients:
recipients.append(recipientActor)
tags[wordStr]={
@ -197,7 +224,11 @@ def addMention(wordStr: str,httpPrefix: str,following: str,replaceMentions: {},r
'name': wordStr,
'type': 'Mention'
}
replaceMentions[wordStr]="<span class=\"h-card\"><a href=\""+httpPrefix+"://"+possibleDomain+"/@"+possibleNickname+"\" class=\"u-url mention\">@<span>"+possibleNickname+"</span></a></span>"
replaceMentions[wordStr]= \
"<span class=\"h-card\"><a href=\""+httpPrefix+ \
"://"+possibleDomain+"/@"+possibleNickname+ \
"\" class=\"u-url mention\">@<span>"+possibleNickname+ \
"</span></a></span>"
return True
return False
@ -244,22 +275,27 @@ def addHtmlTags(baseDir: str,httpPrefix: str, \
# extract mentions and tags from words
for wordStr in words:
if addMention(wordStr,httpPrefix,following,replaceMentions,recipients,hashtags):
if addMention(wordStr,httpPrefix,following, \
replaceMentions,recipients,hashtags):
continue
if addHashTags(wordStr,httpPrefix,originalDomain,replaceHashTags,hashtags):
if addHashTags(wordStr,httpPrefix,originalDomain, \
replaceHashTags,hashtags):
continue
if len(wordStr)>2 and wordStr.startswith(':') and wordStr.endswith(':') and not emojiDict:
if len(wordStr)>2 and wordStr.startswith(':') and \
wordStr.endswith(':') and not emojiDict:
print('Loading emoji lookup')
# emoji.json is generated so that it can be customized and the changes
# will be retained even if default_emoji.json is subsequently updated
if not os.path.isfile(baseDir+'/emoji/emoji.json'):
copyfile(baseDir+'/emoji/default_emoji.json',baseDir+'/emoji/emoji.json')
copyfile(baseDir+'/emoji/default_emoji.json', \
baseDir+'/emoji/emoji.json')
with open(baseDir+'/emoji/emoji.json', 'r') as fp:
emojiDict=commentjson.load(fp)
addEmoji(baseDir,wordStr,httpPrefix,originalDomain,replaceEmoji,hashtags,emojiDict)
addEmoji(baseDir,wordStr,httpPrefix,originalDomain, \
replaceEmoji,hashtags,emojiDict)
# replace words with their html versions
for wordStr,replaceStr in replaceMentions.items():
@ -273,7 +309,8 @@ def addHtmlTags(baseDir: str,httpPrefix: str, \
content=content.replace(' --linebreak-- ','</p><p>')
return '<p>'+content+'</p>'
def getMentionsFromHtml(htmlText: str,matchStr="<span class=\"h-card\"><a href=\"") -> []:
def getMentionsFromHtml(htmlText: str, \
matchStr="<span class=\"h-card\"><a href=\"") -> []:
"""Extracts mentioned actors from the given html content string
"""
mentions=[]

609
daemon.py

File diff suppressed because it is too large Load Diff

View File

@ -132,7 +132,8 @@ def inboxMessageHasParams(messageJson: {}) -> bool:
return False
return True
def inboxPermittedMessage(domain: str,messageJson: {},federationList: []) -> bool:
def inboxPermittedMessage(domain: str,messageJson: {}, \
federationList: []) -> bool:
""" check that we are receiving from a permitted domain
"""
testParam='actor'
@ -160,7 +161,7 @@ def inboxPermittedMessage(domain: str,messageJson: {},federationList: []) -> boo
return True
def validPublishedDate(published) -> bool:
def validPublishedDate(published: str) -> bool:
currTime=datetime.datetime.utcnow()
pubDate=datetime.datetime.strptime(published,"%Y-%m-%dT%H:%M:%SZ")
daysSincePublished = (currTime - pubTime).days
@ -387,7 +388,9 @@ def inboxPostRecipientsAdd(baseDir :str,httpPrefix :str,toList :[], \
followerRecipients=True
return followerRecipients,recipientsDict
def inboxPostRecipients(baseDir :str,postJsonObject :{},httpPrefix :str,domain : str,port :int, debug :bool) -> ([],[]):
def inboxPostRecipients(baseDir :str,postJsonObject :{}, \
httpPrefix :str,domain : str,port :int, \
debug :bool) -> ([],[]):
"""Returns dictionaries containing the recipients of the given post
The shared dictionary contains followers
"""
@ -1052,8 +1055,8 @@ def inboxAfterCapabilities(session,keyId: str,handle: str,messageJson: {}, \
postLog: [],cachedWebfingers: {},personCache: {}, \
queue: [],domain: str,port: int,useTor: bool, \
federationList: [],ocapAlways: bool,debug: bool, \
acceptedCaps: [],
queueFilename :str,destinationFilename :str,
acceptedCaps: [], \
queueFilename :str,destinationFilename :str, \
maxReplies: int,allowDeletion: bool) -> bool:
""" Anything which needs to be done after capabilities checks have passed
"""

View File

@ -372,7 +372,8 @@ def getPosts(session,outboxUrl: str,maxPosts: int, \
break
return personPosts
def deleteAllPosts(baseDir: str,nickname: str, domain: str,boxname: str) -> None:
def deleteAllPosts(baseDir: str, \
nickname: str, domain: str,boxname: str) -> None:
"""Deletes all posts for a person from inbox or outbox
"""
if boxname!='inbox' and boxname!='outbox':
@ -656,8 +657,9 @@ def outboxMessageCreateWrap(httpPrefix: str, \
httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber
return newPost
def postIsAddressedToFollowers(baseDir: str,
nickname: str, domain: str, port: int,httpPrefix: str,
def postIsAddressedToFollowers(baseDir: str, \
nickname: str,domain: str, \
port: int,httpPrefix: str, \
postJsonObject: {}) -> bool:
"""Returns true if the given post is addressed to followers of the nickname
"""
@ -816,13 +818,15 @@ def getMentionedPeople(baseDir: str,httpPrefix: str, \
mentions.append(actor)
return mentions
def createDirectMessagePost(baseDir: str,
nickname: str, domain: str, port: int,httpPrefix: str, \
content: str, followersOnly: bool, saveToFile: bool,
def createDirectMessagePost(baseDir: str, \
nickname: str,domain: str,port: int, \
httpPrefix: str, \
content: str,followersOnly: bool,saveToFile: bool,
clientToServer: bool,\
attachImageFilename: str,mediaType: str, \
imageDescription: str,useBlurhash: bool, \
inReplyTo=None, inReplyToAtomUri=None, subject=None,debug=False) -> {}:
inReplyTo=None,inReplyToAtomUri=None, \
subject=None,debug=False) -> {}:
"""Direct Message post
"""
mentionedPeople=getMentionedPeople(baseDir,httpPrefix,content,domain,debug)
@ -840,9 +844,9 @@ def createDirectMessagePost(baseDir: str,
imageDescription,useBlurhash, \
False,inReplyTo, inReplyToAtomUri, subject)
def createReportPost(baseDir: str,
nickname: str, domain: str, port: int,httpPrefix: str, \
content: str, followersOnly: bool, saveToFile: bool,
def createReportPost(baseDir: str, \
nickname: str,domain: str,port: int,httpPrefix: str, \
content: str, followersOnly: bool, saveToFile: bool, \
clientToServer: bool,\
attachImageFilename: str,mediaType: str, \
imageDescription: str,useBlurhash: bool, \
@ -915,8 +919,9 @@ def createReportPost(baseDir: str,
True,None, None, subject)
return postJsonObject
def threadSendPost(session,postJsonStr: str,federationList: [],\
inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [],
def threadSendPost(session,postJsonStr: str,federationList: [], \
inboxUrl: str, baseDir: str, \
signatureHeaderJson: {},postLog: [], \
debug :bool) -> None:
"""Sends a post with exponential backoff
"""
@ -955,15 +960,17 @@ def threadSendPost(session,postJsonStr: str,federationList: [],\
tries+=1
def sendPost(projectVersion: str, \
session,baseDir: str,nickname: str, domain: str, port: int, \
toNickname: str, toDomain: str, toPort: int, cc: str, \
httpPrefix: str, content: str, followersOnly: bool, \
saveToFile: bool, clientToServer: bool, \
session,baseDir: str,nickname: str,domain: str,port: int, \
toNickname: str,toDomain: str,toPort: int,cc: str, \
httpPrefix: str,content: str,followersOnly: bool, \
saveToFile: bool,clientToServer: bool, \
attachImageFilename: str,mediaType: str, \
imageDescription: str,useBlurhash: bool, \
federationList: [],\
sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \
debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int:
federationList: [], \
sendThreads: [],postLog: [], \
cachedWebfingers: {},personCache: {}, \
debug=False,inReplyTo=None, \
inReplyToAtomUri=None,subject=None) -> int:
"""Post to another inbox
"""
withDigest=True
@ -1061,7 +1068,8 @@ def sendPostViaServer(projectVersion: str, \
attachImageFilename: str,mediaType: str, \
imageDescription: str,useBlurhash: bool, \
cachedWebfingers: {},personCache: {}, \
debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int:
debug=False,inReplyTo=None, \
inReplyToAtomUri=None,subject=None) -> int:
"""Send a post via a proxy (c2s)
"""
if not session:
@ -1566,23 +1574,31 @@ def sendToFollowers(session,baseDir: str, \
print('DEBUG: End of sendToFollowers')
def createInbox(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,ocapAlways: bool,pageNumber=None) -> {}:
def createInbox(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, \
itemsPerPage: int,headerOnly: bool, \
ocapAlways: bool,pageNumber=None) -> {}:
return createBoxBase(baseDir,'inbox',nickname,domain,port,httpPrefix, \
itemsPerPage,headerOnly,True,ocapAlways,pageNumber)
def createDMTimeline(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,ocapAlways: bool,pageNumber=None) -> {}:
def createDMTimeline(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, \
itemsPerPage: int,headerOnly: bool, \
ocapAlways: bool,pageNumber=None) -> {}:
return createBoxBase(baseDir,'dm',nickname,domain,port,httpPrefix, \
itemsPerPage,headerOnly,True,ocapAlways,pageNumber)
def createOutbox(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,authorized: bool,pageNumber=None) -> {}:
def createOutbox(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, \
itemsPerPage: int,headerOnly: bool, \
authorized: bool,pageNumber=None) -> {}:
return createBoxBase(baseDir,'outbox',nickname,domain,port,httpPrefix, \
itemsPerPage,headerOnly,authorized,False,pageNumber)
def createModeration(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \
itemsPerPage: int,headerOnly: bool,ocapAlways: bool,pageNumber=None) -> {}:
def createModeration(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, \
itemsPerPage: int,headerOnly: bool, \
ocapAlways: bool,pageNumber=None) -> {}:
boxDir = createPersonDir(nickname,domain,baseDir,'inbox')
boxname='moderation'
@ -1857,7 +1873,8 @@ def createBoxBase(baseDir: str,boxname: str, \
return boxHeader
return boxItems
def expireCache(baseDir: str,personCache: {},httpPrefix: str,archiveDir: str,maxPostsInBox=256):
def expireCache(baseDir: str,personCache: {}, \
httpPrefix: str,archiveDir: str,maxPostsInBox=256):
"""Thread used to expire actors from the cache and archive old posts
"""
while True:
@ -1866,7 +1883,8 @@ def expireCache(baseDir: str,personCache: {},httpPrefix: str,archiveDir: str,max
expirePersonCache(basedir,personCache)
archivePosts(baseDir,httpPrefix,archiveDir,maxPostsInBox)
def archivePosts(baseDir: str,httpPrefix: str,archiveDir: str,maxPostsInBox=256) -> None:
def archivePosts(baseDir: str,httpPrefix: str, \
archiveDir: str,maxPostsInBox=256) -> None:
"""Archives posts for all accounts
"""
if archiveDir:
@ -1899,8 +1917,10 @@ def archivePosts(baseDir: str,httpPrefix: str,archiveDir: str,maxPostsInBox=256)
'outbox',archiveSubdir, \
maxPostsInBox)
def archivePostsForPerson(httpPrefix: str,nickname: str,domain: str,baseDir: str, \
boxname: str,archiveDir: str,maxPostsInBox=256) -> None:
def archivePostsForPerson(httpPrefix: str,nickname: str,domain: str, \
baseDir: str, \
boxname: str,archiveDir: str, \
maxPostsInBox=256) -> None:
"""Retain a maximum number of posts within the given box
Move any others to an archive directory
"""
@ -2005,8 +2025,11 @@ def sendCapabilitiesUpdate(session,baseDir: str,httpPrefix: str, \
sendThreads,postLog,cachedWebfingers, \
personCache,debug,projectVersion)
def populateRepliesJson(baseDir: str,nickname: str,domain: str,postRepliesFilename: str,authorized: bool,repliesJson: {}) -> None:
# populate the items list with replies
def populateRepliesJson(baseDir: str,nickname: str,domain: str, \
postRepliesFilename: str,authorized: bool, \
repliesJson: {}) -> None:
"""populate the items list with replies
"""
repliesBoxes=['outbox','inbox']
with open(postRepliesFilename,'r') as repliesFile:
for messageId in repliesFile: