diff --git a/daemon.py b/daemon.py index 1de6c9d4a..e3e74108a 100644 --- a/daemon.py +++ b/daemon.py @@ -1802,6 +1802,7 @@ class PubServer(BaseHTTPRequestHandler): messageFields=msg.get_payload(decode=False).split(boundary) fields={} filename=None + attachmentMediaType=None for f in messageFields: if f=='--': continue @@ -1837,6 +1838,7 @@ class PubServer(BaseHTTPRequestHandler): if extension=='jpeg': extension='jpg' filename=filenameBase+'.'+extension + attachmentMediaType=mType break if filename and imageLocation>-1: # locate the beginning of the image, after any @@ -1875,7 +1877,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain,self.server.port, \ self.server.httpPrefix, \ fields['message'],False,False,False, \ - filename,fields['imageDescription'],True, \ + filename,attachmentMediaType,fields['imageDescription'],True, \ fields['replyTo'], fields['replyTo'],fields['subject']) if messageJson: self.postToNickname=nickname @@ -1897,7 +1899,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain,self.server.port, \ self.server.httpPrefix, \ fields['message'],False,False,False, \ - filename,fields['imageDescription'],True, \ + filename,attachmentMediaType,fields['imageDescription'],True, \ fields['replyTo'], fields['replyTo'],fields['subject']) if messageJson: self.postToNickname=nickname @@ -1919,7 +1921,7 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain,self.server.port, \ self.server.httpPrefix, \ fields['message'],True,False,False, \ - filename,fields['imageDescription'],True, \ + filename,attachmentMediaType,fields['imageDescription'],True, \ fields['replyTo'], fields['replyTo'],fields['subject']) if messageJson: self.postToNickname=nickname @@ -1943,7 +1945,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain,self.server.port, \ self.server.httpPrefix, \ fields['message'],True,False,False, \ - filename,fields['imageDescription'],True, \ + filename,attachmentMediaType, \ + fields['imageDescription'],True, \ fields['replyTo'],fields['replyTo'], \ fields['subject'], \ self.server.debug) @@ -1963,6 +1966,9 @@ class PubServer(BaseHTTPRequestHandler): return -1 if postType=='newreport': + if attachmentMediaType: + if attachmentMediaType!='image': + return -1 # So as to be sure that this only goes to moderators # and not accounts being reported we disable any # included fediverse addresses by replacing '@' with '-at-' @@ -1973,7 +1979,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.domain,self.server.port, \ self.server.httpPrefix, \ fields['message'],True,False,False, \ - filename,fields['imageDescription'],True, \ + filename,attachmentMediaType, \ + fields['imageDescription'],True, \ self.server.debug,fields['subject']) if messageJson: self.postToNickname=nickname @@ -1984,13 +1991,16 @@ class PubServer(BaseHTTPRequestHandler): if postType=='newshare': if not fields.get('itemType'): - return False + return -1 if not fields.get('category'): - return False + return -1 if not fields.get('location'): - return False + return -1 if not fields.get('duration'): - return False + return -1 + if attachmentMediaType: + if attachmentMediaType!='image': + return -1 addShare(self.server.baseDir, \ self.server.httpPrefix, \ nickname, \ diff --git a/epicyon.py b/epicyon.py index 442fd7e2d..17f9e4df2 100644 --- a/epicyon.py +++ b/epicyon.py @@ -62,6 +62,7 @@ from utils import getNicknameFromActor from utils import followPerson from utils import validNickname from media import archiveMedia +from media import getAttachmentMediaType from delete import sendDeleteViaServer from like import sendLikeViaServer from like import sendUndoLikeViaServer @@ -525,6 +526,9 @@ if args.message: cachedWebfingers={} subject=args.subject attach=args.attach + mediaType=None + if attach: + mediaType=getAttachmentMediaType(attach) replyTo=args.replyto followersOnly=False print('Sending post to '+args.sendto) @@ -534,7 +538,8 @@ if args.message: domain,port, \ toNickname,toDomain,toPort,ccUrl, \ httpPrefix,sendMessage,followersOnly, \ - attach,attachedImageDescription,useBlurhash, \ + attach,mediaType, \ + attachedImageDescription,useBlurhash, \ cachedWebfingers,personCache, \ args.debug,replyTo,replyTo,subject) for i in range(10): diff --git a/media.py b/media.py index 452b5e19d..8bbcebc54 100644 --- a/media.py +++ b/media.py @@ -47,9 +47,29 @@ def getMediaPath() -> str: currTime=datetime.datetime.utcnow() weeksSinceEpoch=int((currTime - datetime.datetime(1970,1,1)).days/7) return 'media/'+str(weeksSinceEpoch) - + +def getAttachmentMediaType(filename: str) -> str: + """Returns the type of media for the given file + image, video or audio + """ + mediaType=None + imageTypes=['png','jpg','jpeg','gif'] + for mType in imageTypes: + if filename.endswith('.'+mType): + return 'image' + videoTypes=['mp4','webm','ogv'] + for mType in videoTypes: + if filename.endswith('.'+mType): + return 'video' + audioTypes=['mp3','ogg'] + for mType in audioTypes: + if filename.endswith('.'+mType): + return 'audio' + return mediaType + def attachImage(baseDir: str,httpPrefix: str,domain: str,port: int, \ - postJson: {},imageFilename: str,description: str, \ + postJson: {},imageFilename: str, \ + mediaType: str,description: str, \ useBlurhash: bool) -> {}: """Attaches an image to a json object post The description can be None @@ -58,14 +78,16 @@ def attachImage(baseDir: str,httpPrefix: str,domain: str,port: int, \ if not isImage(imageFilename): return postJson - mediaType='image/png' - fileExtension='png' - if imageFilename.endswith('.jpg'): - mediaType='image/jpeg' + acceptedTypes=['png','jpg','gif','mp4','webm','ogv','mp3','ogg'] + for mType in acceptedTypes: + if imageFilename.endswith('.'+mType): + fileExtension=mType + if mType=='jpg': + mType='jpeg' + mediaType=mediaType+'/'+fileExtension + + if fileExtension=='jpeg': fileExtension='jpg' - if imageFilename.endswith('.gif'): - mediaType='image/gif' - fileExtension='gif' if port: if port!=80 and port!=443: @@ -84,7 +106,7 @@ def attachImage(baseDir: str,httpPrefix: str,domain: str,port: int, \ 'type': 'Document', 'url': httpPrefix+'://'+domain+'/'+mediaPath } - if useBlurhash: + if useBlurhash and not mediaType.startswith('video'): attachmentJson['blurhash']=getImageHash(imageFilename) postJson['attachment']=[attachmentJson] diff --git a/posts.py b/posts.py index 4ea0c5513..be90b441a 100644 --- a/posts.py +++ b/posts.py @@ -423,7 +423,7 @@ def updateHashtagsIndex(baseDir: str,tag: {},newPostId: str) -> None: def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \ toUrl: str, ccUrl: str, httpPrefix: str, content: str, \ followersOnly: bool, saveToFile: bool, clientToServer: bool, \ - attachImageFilename: str,imageDescription: str, \ + attachImageFilename: str,mediaType: str,imageDescription: str, \ useBlurhash: bool,isModerationReport: bool,inReplyTo=None, \ inReplyToAtomUri=None, subject=None) -> {}: """Creates a message @@ -543,7 +543,7 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \ newPost['object']= \ attachImage(baseDir,httpPrefix,domain,port, \ newPost['object'],attachImageFilename, \ - imageDescription,useBlurhash) + mediaType,imageDescription,useBlurhash) else: newPost = { "@context": "https://www.w3.org/ns/activitystreams", @@ -579,7 +579,7 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \ newPost= \ attachImage(baseDir,httpPrefix,domain,port, \ newPost,attachImageFilename, \ - imageDescription,useBlurhash) + mediaType,imageDescription,useBlurhash) if ccUrl: if len(ccUrl)>0: newPost['cc']=[ccUrl] @@ -707,7 +707,8 @@ def createPublicPost(baseDir: str, nickname: str, domain: str, port: int,httpPrefix: str, \ content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool,\ - attachImageFilename: str,imageDescription: str,useBlurhash: bool, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}: """Public post """ @@ -721,14 +722,16 @@ def createPublicPost(baseDir: str, httpPrefix+'://'+domainFull+'/users/'+nickname+'/followers', \ httpPrefix, content, followersOnly, saveToFile, \ clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ False,inReplyTo,inReplyToAtomUri,subject) def createUnlistedPost(baseDir: str, nickname: str, domain: str, port: int,httpPrefix: str, \ content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool,\ - attachImageFilename: str,imageDescription: str,useBlurhash: bool, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}: """Unlisted post. This has the #Public and followers links inverted. """ @@ -742,14 +745,16 @@ def createUnlistedPost(baseDir: str, 'https://www.w3.org/ns/activitystreams#Public', \ httpPrefix, content, followersOnly, saveToFile, \ clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ False,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, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}: """Followers only post """ @@ -763,7 +768,8 @@ def createFollowersOnlyPost(baseDir: str, None, httpPrefix, content, followersOnly, saveToFile, \ clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ False,inReplyTo, inReplyToAtomUri, subject) def getMentionedPeople(baseDir: str,httpPrefix: str, \ @@ -801,7 +807,8 @@ 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, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ inReplyTo=None, inReplyToAtomUri=None, subject=None,debug=False) -> {}: """Direct Message post """ @@ -816,14 +823,16 @@ def createDirectMessagePost(baseDir: str, postTo,postCc, \ httpPrefix, content, followersOnly, saveToFile, \ clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ False,inReplyTo, inReplyToAtomUri, subject) def createReportPost(baseDir: str, nickname: str, domain: str, port: int,httpPrefix: str, \ content: str, followersOnly: bool, saveToFile: bool, clientToServer: bool,\ - attachImageFilename: str,imageDescription: str,useBlurhash: bool, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ debug: bool,subject=None) -> {}: """Send a report to moderators """ @@ -888,7 +897,8 @@ def createReportPost(baseDir: str, toUrl,postCc, \ httpPrefix, content, followersOnly, saveToFile, \ clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ True,None, None, subject) return postJsonObject @@ -936,7 +946,8 @@ def sendPost(projectVersion: str, \ toNickname: str, toDomain: str, toPort: int, cc: str, \ httpPrefix: str, content: str, followersOnly: bool, \ saveToFile: bool, clientToServer: bool, \ - attachImageFilename: str,imageDescription: str,useBlurhash: bool, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ federationList: [],\ sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \ debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int: @@ -991,7 +1002,8 @@ def sendPost(projectVersion: str, \ createPostBase(baseDir,nickname,domain,port, \ toPersonId,cc,httpPrefix,content, \ followersOnly,saveToFile,clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ False,inReplyTo,inReplyToAtomUri,subject) # get the senders private key @@ -1033,7 +1045,8 @@ def sendPostViaServer(projectVersion: str, \ fromDomain: str, fromPort: int, \ toNickname: str, toDomain: str, toPort: int, cc: str, \ httpPrefix: str, content: str, followersOnly: bool, \ - attachImageFilename: str,imageDescription: str,useBlurhash: bool, \ + attachImageFilename: str,mediaType: str, \ + imageDescription: str,useBlurhash: bool, \ cachedWebfingers: {},personCache: {}, \ debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int: """Send a post via a proxy (c2s) @@ -1102,7 +1115,8 @@ def sendPostViaServer(projectVersion: str, \ fromNickname,fromDomain,fromPort, \ toPersonId,cc,httpPrefix,content, \ followersOnly,saveToFile,clientToServer, \ - attachImageFilename,imageDescription,useBlurhash, \ + attachImageFilename,mediaType, \ + imageDescription,useBlurhash, \ False,inReplyTo,inReplyToAtomUri,subject) authHeader=createBasicAuthHeader(fromNickname,password) diff --git a/tests.py b/tests.py index 4d7f1d61d..cf2ccc1e7 100644 --- a/tests.py +++ b/tests.py @@ -60,6 +60,7 @@ from like import sendLikeViaServer from announce import announcePublic from announce import sendAnnounceViaServer from media import getMediaPath +from media import getAttachmentMediaType from delete import sendDeleteViaServer from inbox import validInbox from inbox import validInboxFilenames @@ -368,6 +369,7 @@ def testPostMessageBetweenServers(): alicePersonCache={} aliceCachedWebfingers={} attachedImageFilename=baseDir+'/img/logo.png' + mediaType=getAttachmentMediaType(attachedImageFilename) attachedImageDescription='Logo' useBlurhash=True # nothing in Alice's outbox @@ -379,7 +381,7 @@ def testPostMessageBetweenServers(): sessionAlice,aliceDir,'alice', aliceDomain, alicePort, \ 'bob', bobDomain, bobPort, ccUrl, httpPrefix, \ 'Why is a mouse when it spins? #sillyquestion', followersOnly, \ - saveToFile, clientToServer,attachedImageFilename, \ + saveToFile, clientToServer,attachedImageFilename,mediaType, \ attachedImageDescription,useBlurhash, federationList, \ aliceSendThreads, alicePostLog, aliceCachedWebfingers, \ alicePersonCache,inReplyTo, inReplyToAtomUri, subject) @@ -620,7 +622,7 @@ def testFollowBetweenServers(): sessionEve,eveDir,'eve', eveDomain, evePort, \ 'bob', bobDomain, bobPort, ccUrl, \ httpPrefix, 'Eve message', followersOnly, \ - saveToFile, clientToServer,None,None, \ + saveToFile, clientToServer,None,None,None, \ useBlurhash, federationList, eveSendThreads, \ evePostLog, eveCachedWebfingers, \ evePersonCache,inReplyTo, inReplyToAtomUri, subject) @@ -655,7 +657,7 @@ def testFollowBetweenServers(): sessionAlice,aliceDir,'alice', aliceDomain, alicePort, \ 'bob', bobDomain, bobPort, ccUrl, \ httpPrefix, 'Alice message', followersOnly, saveToFile, \ - clientToServer,None,None,useBlurhash, federationList, \ + clientToServer,None,None,None,useBlurhash, federationList, \ aliceSendThreads, alicePostLog, aliceCachedWebfingers, \ alicePersonCache,inReplyTo, inReplyToAtomUri, subject) print('sendResult: '+str(sendResult)) @@ -1136,6 +1138,7 @@ def testClientToServer(): sessionAlice = createSession(aliceDomain,alicePort,useTor) followersOnly=False attachedImageFilename=baseDir+'/img/logo.png' + mediaType=getAttachmentMediaType(attachedImageFilename) attachedImageDescription='Logo' useBlurhash=False cachedWebfingers={} @@ -1151,7 +1154,8 @@ def testClientToServer(): aliceDomain,alicePort, \ 'bob',bobDomain,bobPort,None, \ httpPrefix,'Sent from my ActivityPub client',followersOnly, \ - attachedImageFilename,attachedImageDescription,useBlurhash, \ + attachedImageFilename,mediaType, \ + attachedImageDescription,useBlurhash, \ cachedWebfingers,personCache, \ True,None,None,None) print('sendResult: '+str(sendResult))