forked from indymedia/epicyon
Connect new posts to web interface
parent
744b345b30
commit
e6c246fc8e
106
daemon.py
106
daemon.py
|
@ -30,6 +30,9 @@ from posts import savePostToBox
|
||||||
from posts import sendToFollowers
|
from posts import sendToFollowers
|
||||||
from posts import postIsAddressedToPublic
|
from posts import postIsAddressedToPublic
|
||||||
from posts import sendToNamedAddresses
|
from posts import sendToNamedAddresses
|
||||||
|
from posts import createPublicPost
|
||||||
|
from posts import createFollowersOnlyPost
|
||||||
|
from posts import createDirectMessagePost
|
||||||
from inbox import inboxPermittedMessage
|
from inbox import inboxPermittedMessage
|
||||||
from inbox import inboxMessageHasParams
|
from inbox import inboxMessageHasParams
|
||||||
from inbox import runInboxQueue
|
from inbox import runInboxQueue
|
||||||
|
@ -1068,6 +1071,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
# email style encoding message/rfc822
|
# email style encoding message/rfc822
|
||||||
messageFields=msg.get_payload(decode=False).split(boundary)
|
messageFields=msg.get_payload(decode=False).split(boundary)
|
||||||
fields={}
|
fields={}
|
||||||
|
filename=None
|
||||||
for f in messageFields:
|
for f in messageFields:
|
||||||
if ' name="' in f:
|
if ' name="' in f:
|
||||||
postStr=f.split(' name="',1)[1]
|
postStr=f.split(' name="',1)[1]
|
||||||
|
@ -1089,7 +1093,6 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
# of an image
|
# of an image
|
||||||
searchStr=b'Content-Type: image/png'
|
searchStr=b'Content-Type: image/png'
|
||||||
imageLocation=postBytes.find(searchStr)
|
imageLocation=postBytes.find(searchStr)
|
||||||
filename=None
|
|
||||||
filenameBase=self.server.baseDir+'/accounts/'+nickname+'@'+self.server.domain+'/upload'
|
filenameBase=self.server.baseDir+'/accounts/'+nickname+'@'+self.server.domain+'/upload'
|
||||||
if imageLocation:
|
if imageLocation:
|
||||||
filename=filenameBase+'.png'
|
filename=filenameBase+'.png'
|
||||||
|
@ -1117,43 +1120,68 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
fd.write(postBytes[startPos:])
|
fd.write(postBytes[startPos:])
|
||||||
fd.close()
|
fd.close()
|
||||||
|
|
||||||
postSubject=None
|
# send the post
|
||||||
postMessage=None
|
|
||||||
postImageDescription=None
|
if not fields.get('message'):
|
||||||
postImage=None
|
return False
|
||||||
postType=None
|
|
||||||
postCategory=None
|
if not fields.get('imageDescription'):
|
||||||
postLocation=None
|
fields['imageDescription']=None
|
||||||
for postKey,postValue in fields.items():
|
if not fields.get('subject'):
|
||||||
if postKey=='subject':
|
fields['subject']=None
|
||||||
postSubject=postValue
|
if not fields.get('replyTo'):
|
||||||
elif postKey=='message':
|
fields['replyTo']=None
|
||||||
postMessage=postValue
|
|
||||||
elif postKey=='imageDescription':
|
if postType=='newpost':
|
||||||
postImageDescription=postValue
|
messageJson= \
|
||||||
elif postKey=='postType':
|
createPublicPost(self.server.baseDir, \
|
||||||
postType=postValue
|
nickname, \
|
||||||
elif postKey=='category':
|
self.server.domain,self.server.port, \
|
||||||
postCategory=postValue
|
self.server.httpPrefix, \
|
||||||
elif postKey=='location':
|
fields['message'],False,False,False, \
|
||||||
postLocation=postValue
|
filename,fields['imageDescription'],True, \
|
||||||
if self.server.debug:
|
fields['replyTo'], fields['replyTo'],fields['subject'])
|
||||||
if postSubject:
|
if messageJson:
|
||||||
print('subject: '+postSubject)
|
queueStatus=self._updateInboxQueue(nickname,messageJson)
|
||||||
if postMessage:
|
if queueStatus==0:
|
||||||
print('message: '+postMessage)
|
return True
|
||||||
if postImageDescription:
|
|
||||||
print('image description: '+postImageDescription)
|
if postType=='newfollowers':
|
||||||
if postType:
|
messageJson= \
|
||||||
print('type: '+postType)
|
createFollowersOnlyPost(self.server.baseDir, \
|
||||||
if postCategory:
|
nickname, \
|
||||||
print('category: '+postCategory)
|
self.server.domain,self.server.port, \
|
||||||
if postLocation:
|
self.server.httpPrefix, \
|
||||||
print('location: '+postLocation)
|
fields['message'],True,False,False, \
|
||||||
if not postMessage:
|
filename,fields['imageDescription'],True, \
|
||||||
return False
|
fields['replyTo'], fields['replyTo'],fields['subject'])
|
||||||
return True
|
if messageJson:
|
||||||
return False
|
queueStatus=self._updateInboxQueue(nickname,messageJson)
|
||||||
|
if queueStatus==0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if postType=='newdm':
|
||||||
|
messageJson= \
|
||||||
|
createDirectMessagePost(self.server.baseDir, \
|
||||||
|
nickname, \
|
||||||
|
self.server.domain,self.server.port, \
|
||||||
|
self.server.httpPrefix, \
|
||||||
|
fields['message'],True,False,False, \
|
||||||
|
filename,fields['imageDescription'],True, \
|
||||||
|
fields['replyTo'], fields['replyTo'],fields['subject'])
|
||||||
|
if messageJson:
|
||||||
|
queueStatus=self._updateInboxQueue(nickname,messageJson)
|
||||||
|
if queueStatus==0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if postType=='newunlisted':
|
||||||
|
# TODO
|
||||||
|
return True
|
||||||
|
|
||||||
|
if postType=='newshare':
|
||||||
|
# TODO
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
|
@ -1449,7 +1477,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
else:
|
else:
|
||||||
if self.path == '/sharedInbox' or self.path == '/inbox':
|
if self.path == '/sharedInbox' or self.path == '/inbox':
|
||||||
print('DEBUG: POST to shared inbox')
|
print('DEBUG: POST to shared inbox')
|
||||||
queueStatus-_updateInboxQueue('inbox',messageJson)
|
queueStatus=_updateInboxQueue('inbox',messageJson)
|
||||||
if queueStatus==0:
|
if queueStatus==0:
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
|
@ -11,7 +11,6 @@ from person import createSharedInbox
|
||||||
from person import createCapabilitiesInbox
|
from person import createCapabilitiesInbox
|
||||||
from person import setPreferredNickname
|
from person import setPreferredNickname
|
||||||
from person import setBio
|
from person import setBio
|
||||||
from person import validNickname
|
|
||||||
from person import setProfileImage
|
from person import setProfileImage
|
||||||
from skills import setSkillLevel
|
from skills import setSkillLevel
|
||||||
from roles import setRole
|
from roles import setRole
|
||||||
|
@ -44,7 +43,6 @@ from daemon import runDaemon
|
||||||
import socket
|
import socket
|
||||||
from follow import clearFollows
|
from follow import clearFollows
|
||||||
from follow import clearFollowers
|
from follow import clearFollowers
|
||||||
from utils import followPerson
|
|
||||||
from follow import followerOfPerson
|
from follow import followerOfPerson
|
||||||
from follow import unfollowPerson
|
from follow import unfollowPerson
|
||||||
from follow import unfollowerOfPerson
|
from follow import unfollowerOfPerson
|
||||||
|
@ -60,6 +58,8 @@ from auth import removePassword
|
||||||
from auth import createPassword
|
from auth import createPassword
|
||||||
from utils import getDomainFromActor
|
from utils import getDomainFromActor
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
|
from utils import followPerson
|
||||||
|
from utils import validNickname
|
||||||
from media import archiveMedia
|
from media import archiveMedia
|
||||||
from delete import sendDeleteViaServer
|
from delete import sendDeleteViaServer
|
||||||
from like import sendLikeViaServer
|
from like import sendLikeViaServer
|
||||||
|
|
|
@ -11,7 +11,7 @@ import commentjson
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from person import validNickname
|
from utils import validNickname
|
||||||
from utils import domainPermitted
|
from utils import domainPermitted
|
||||||
from utils import getDomainFromActor
|
from utils import getDomainFromActor
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
|
|
11
person.py
11
person.py
|
@ -22,6 +22,7 @@ from posts import createOutbox
|
||||||
from auth import storeBasicCredentials
|
from auth import storeBasicCredentials
|
||||||
from roles import setRole
|
from roles import setRole
|
||||||
from media import removeMetaData
|
from media import removeMetaData
|
||||||
|
from utils import validNickname
|
||||||
|
|
||||||
def generateRSAKey() -> (str,str):
|
def generateRSAKey() -> (str,str):
|
||||||
key = RSA.generate(2048)
|
key = RSA.generate(2048)
|
||||||
|
@ -259,16 +260,6 @@ def createCapabilitiesInbox(baseDir: str,nickname: str,domain: str,port: int, \
|
||||||
"""Generates the capabilities inbox to sign requests
|
"""Generates the capabilities inbox to sign requests
|
||||||
"""
|
"""
|
||||||
return createPersonBase(baseDir,nickname,domain,port,httpPrefix,True,None)
|
return createPersonBase(baseDir,nickname,domain,port,httpPrefix,True,None)
|
||||||
|
|
||||||
def validNickname(nickname: str) -> bool:
|
|
||||||
forbiddenChars=['.',' ','/','?',':',';','@']
|
|
||||||
for c in forbiddenChars:
|
|
||||||
if c in nickname:
|
|
||||||
return False
|
|
||||||
reservedNames=['inbox','outbox','following','followers','capabilities']
|
|
||||||
if nickname in reservedNames:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def personLookup(domain: str,path: str,baseDir: str) -> {}:
|
def personLookup(domain: str,path: str,baseDir: str) -> {}:
|
||||||
"""Lookup the person for an given nickname
|
"""Lookup the person for an given nickname
|
||||||
|
|
68
posts.py
68
posts.py
|
@ -35,6 +35,7 @@ from utils import urlPermitted
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
from utils import getDomainFromActor
|
from utils import getDomainFromActor
|
||||||
from utils import deletePost
|
from utils import deletePost
|
||||||
|
from utils import validNickname
|
||||||
from capabilities import getOcapFilename
|
from capabilities import getOcapFilename
|
||||||
from capabilities import capabilitiesUpdate
|
from capabilities import capabilitiesUpdate
|
||||||
from media import attachImage
|
from media import attachImage
|
||||||
|
@ -591,7 +592,7 @@ def createPublicPost(baseDir: str,
|
||||||
clientToServer: bool,\
|
clientToServer: bool,\
|
||||||
attachImageFilename: str,imageDescription: str,useBlurhash: bool, \
|
attachImageFilename: str,imageDescription: str,useBlurhash: bool, \
|
||||||
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
||||||
"""Public post to the outbox
|
"""Public post
|
||||||
"""
|
"""
|
||||||
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', \
|
||||||
|
@ -601,6 +602,71 @@ def createPublicPost(baseDir: str,
|
||||||
attachImageFilename,imageDescription,useBlurhash, \
|
attachImageFilename,imageDescription,useBlurhash, \
|
||||||
inReplyTo, inReplyToAtomUri, subject)
|
inReplyTo, inReplyToAtomUri, subject)
|
||||||
|
|
||||||
|
def createFollowersOnlyPost(baseDir: str,
|
||||||
|
nickname: str, domain: str, port: int,httpPrefix: str, \
|
||||||
|
content: str, followersOnly: bool, saveToFile: bool,
|
||||||
|
clientToServer: bool,\
|
||||||
|
attachImageFilename: str,imageDescription: str,useBlurhash: bool, \
|
||||||
|
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
||||||
|
"""Followers only post
|
||||||
|
"""
|
||||||
|
return createPostBase(baseDir,nickname, domain, port, \
|
||||||
|
httpPrefix+'://'+domain+'/users/'+nickname+'/followers', \
|
||||||
|
None,
|
||||||
|
httpPrefix, content, followersOnly, saveToFile, \
|
||||||
|
clientToServer, \
|
||||||
|
attachImageFilename,imageDescription,useBlurhash, \
|
||||||
|
inReplyTo, inReplyToAtomUri, subject)
|
||||||
|
|
||||||
|
def getMentionedPeople(baseDir: str,httpPrefix: str,content: str,domain: str) -> []:
|
||||||
|
"""Extracts a list of mentioned actors from the given message content
|
||||||
|
"""
|
||||||
|
if '@' not in content:
|
||||||
|
return None
|
||||||
|
mentions=[]
|
||||||
|
words=content.split(' ')
|
||||||
|
for wrd in words:
|
||||||
|
if wrd.startswith('@'):
|
||||||
|
handle=wrd[1:]
|
||||||
|
if '@' not in handle:
|
||||||
|
handle=handle+'@'+domain
|
||||||
|
if not os.path.isdir(baseDir+'/accounts/'+handle):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
externalDomain=handle.split('@')[1]
|
||||||
|
if not ('.' in externalDomain or externalDomain=='localhost'):
|
||||||
|
continue
|
||||||
|
mentionedNickname=handle.split('@')[0]
|
||||||
|
if not validNickname(mentionedNickname):
|
||||||
|
continue
|
||||||
|
actor=httpPrefix+'://'+handle.split('@')[1]+'/users/'+mentionedNickname
|
||||||
|
mentions.append(actor)
|
||||||
|
return actor
|
||||||
|
|
||||||
|
def createDirectMessagePost(baseDir: str,
|
||||||
|
nickname: str, domain: str, port: int,httpPrefix: str, \
|
||||||
|
content: str, followersOnly: bool, saveToFile: bool,
|
||||||
|
clientToServer: bool,\
|
||||||
|
attachImageFilename: str,imageDescription: str,useBlurhash: bool, \
|
||||||
|
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
|
||||||
|
"""Direct Message post
|
||||||
|
"""
|
||||||
|
mentionedPeople=getMentionedPeople(baseDir,httpPrefix,content,domain)
|
||||||
|
postTo=None
|
||||||
|
postCc=None
|
||||||
|
if not mentionedPeople:
|
||||||
|
return None
|
||||||
|
if len(mentionedPeople)==1:
|
||||||
|
postTo=mentionedPeople[0]
|
||||||
|
if len(mentionedPeople)>1:
|
||||||
|
postCc=mentionedPeople[1]
|
||||||
|
return createPostBase(baseDir,nickname, domain, port, \
|
||||||
|
postTo,postCc, \
|
||||||
|
httpPrefix, content, followersOnly, saveToFile, \
|
||||||
|
clientToServer, \
|
||||||
|
attachImageFilename,imageDescription,useBlurhash, \
|
||||||
|
inReplyTo, inReplyToAtomUri, subject)
|
||||||
|
|
||||||
def threadSendPost(session,postJsonObject: {},federationList: [],\
|
def threadSendPost(session,postJsonObject: {},federationList: [],\
|
||||||
inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [],
|
inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [],
|
||||||
debug :bool) -> None:
|
debug :bool) -> None:
|
||||||
|
|
|
@ -11,11 +11,11 @@ import commentjson
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from person import validNickname
|
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from auth import createBasicAuthHeader
|
from auth import createBasicAuthHeader
|
||||||
from posts import getPersonBox
|
from posts import getPersonBox
|
||||||
from session import postJson
|
from session import postJson
|
||||||
|
from utils import validNickname
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
from utils import getDomainFromActor
|
from utils import getDomainFromActor
|
||||||
from media import removeMetaData
|
from media import removeMetaData
|
||||||
|
|
10
utils.py
10
utils.py
|
@ -190,3 +190,13 @@ def deletePost(baseDir: str,httpPrefix: str,nickname: str,domain: str,postFilena
|
||||||
os.remove(repliesFilename)
|
os.remove(repliesFilename)
|
||||||
# finally, remove the post itself
|
# finally, remove the post itself
|
||||||
os.remove(postFilename)
|
os.remove(postFilename)
|
||||||
|
|
||||||
|
def validNickname(nickname: str) -> bool:
|
||||||
|
forbiddenChars=['.',' ','/','?',':',';','@']
|
||||||
|
for c in forbiddenChars:
|
||||||
|
if c in nickname:
|
||||||
|
return False
|
||||||
|
reservedNames=['inbox','outbox','following','followers','capabilities']
|
||||||
|
if nickname in reservedNames:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
Loading…
Reference in New Issue