From ec8ae64937b7ce096d1ff0409d54aad70f0126b2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 8 Nov 2021 18:09:24 +0000 Subject: [PATCH] Set content license on images --- daemon.py | 59 ++++++++++++++++++++++++------------- desktop_client.py | 13 +++++++++ epicyon.py | 30 ++++++++++--------- inbox.py | 22 +++++++++----- media.py | 15 ++++++---- newsdaemon.py | 9 ++++-- outbox.py | 6 ++-- person.py | 6 ++-- posts.py | 74 ++++++++++++++++++++++++++++++----------------- schedule.py | 3 +- shares.py | 10 ++++--- tests.py | 48 ++++++++++++++++++++---------- 12 files changed, 196 insertions(+), 99 deletions(-) diff --git a/daemon.py b/daemon.py index 031790be3..7efe607a8 100644 --- a/daemon.py +++ b/daemon.py @@ -508,7 +508,8 @@ class PubServer(BaseHTTPRequestHandler): location, False, self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: # name field contains the answer messageJson['object']['name'] = answer @@ -1281,7 +1282,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.maxLikeCount, self.server.maxRecentPosts, self.server.CWlists, - self.server.listsEnabled) + self.server.listsEnabled, + self.server.contentLicenseUrl) def _getOutboxThreadIndex(self, nickname: str, maxOutboxThreadsPerAccount: int) -> int: @@ -4357,7 +4359,7 @@ class PubServer(BaseHTTPRequestHandler): domain: str, domainFull: str, onionDomain: str, i2pDomain: str, debug: bool, allowLocalNetworkAccess: bool, - systemLanguage: str) -> None: + systemLanguage: str, contentLicenseUrl: str) -> None: """Updates your user profile after editing via the Edit button on the profile screen """ @@ -4504,7 +4506,8 @@ class PubServer(BaseHTTPRequestHandler): if self.server.lowBandwidth: convertImageToLowBandwidth(filename) processMetaData(baseDir, nickname, domain, - filename, postImageFilename, city) + filename, postImageFilename, city, + contentLicenseUrl) if os.path.isfile(postImageFilename): print('profile update POST ' + mType + ' image, zip or font saved to ' + @@ -15259,7 +15262,8 @@ class PubServer(BaseHTTPRequestHandler): def _receiveNewPostProcess(self, postType: str, path: str, headers: {}, length: int, postBytes, boundary: str, callingDomain: str, cookie: str, - authorized: bool) -> int: + authorized: bool, + contentLicenseUrl: str) -> int: # Note: this needs to happen synchronously # 0=this is not a new post # 1=new post success @@ -15336,7 +15340,8 @@ class PubServer(BaseHTTPRequestHandler): convertImageToLowBandwidth(filename) processMetaData(self.server.baseDir, nickname, self.server.domain, - filename, postImageFilename, city) + filename, postImageFilename, city, + contentLicenseUrl) if os.path.isfile(postImageFilename): print('POST media saved to ' + postImageFilename) else: @@ -15463,7 +15468,8 @@ class PubServer(BaseHTTPRequestHandler): fields['location'], False, self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if fields['schedulePost']: return 1 @@ -15545,7 +15551,8 @@ class PubServer(BaseHTTPRequestHandler): fields['location'], self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if fields['schedulePost']: return 1 @@ -15637,7 +15644,8 @@ class PubServer(BaseHTTPRequestHandler): attachmentMediaType, imgDescription, city, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) replaceYouTube(postJsonObject, self.server.YTReplacementDomain, @@ -15695,7 +15703,8 @@ class PubServer(BaseHTTPRequestHandler): fields['location'], self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if fields['schedulePost']: return 1 @@ -15746,7 +15755,8 @@ class PubServer(BaseHTTPRequestHandler): fields['location'], self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if fields['schedulePost']: return 1 @@ -15801,7 +15811,8 @@ class PubServer(BaseHTTPRequestHandler): fields['location'], self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if fields['schedulePost']: return 1 @@ -15854,7 +15865,8 @@ class PubServer(BaseHTTPRequestHandler): fields['location'], self.server.systemLanguage, conversationId, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if fields['schedulePost']: return 1 @@ -15890,7 +15902,8 @@ class PubServer(BaseHTTPRequestHandler): city, self.server.debug, fields['subject'], self.server.systemLanguage, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if self._postToOutbox(messageJson, self.server.projectVersion, @@ -15931,7 +15944,8 @@ class PubServer(BaseHTTPRequestHandler): fields['subject'], intDuration, self.server.systemLanguage, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if messageJson: if self.server.debug: print('DEBUG: new Question') @@ -16003,7 +16017,8 @@ class PubServer(BaseHTTPRequestHandler): city, itemPrice, itemCurrency, self.server.systemLanguage, self.server.translate, sharesFileType, - self.server.lowBandwidth) + self.server.lowBandwidth, + self.server.contentLicenseUrl) if filename: if os.path.isfile(filename): try: @@ -16018,7 +16033,8 @@ class PubServer(BaseHTTPRequestHandler): def _receiveNewPost(self, postType: str, path: str, callingDomain: str, cookie: str, - authorized: bool) -> int: + authorized: bool, + contentLicenseUrl: str) -> int: """A new post has been created This creates a thread to send the new post """ @@ -16120,7 +16136,8 @@ class PubServer(BaseHTTPRequestHandler): path, headers, length, postBytes, boundary, callingDomain, cookie, - authorized) + authorized, + contentLicenseUrl) return pageNumber def _cryptoAPIreadHandle(self): @@ -16417,7 +16434,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.onionDomain, self.server.i2pDomain, self.server.debug, self.server.allowLocalNetworkAccess, - self.server.systemLanguage) + self.server.systemLanguage, + self.server.contentLicenseUrl) return if authorized and self.path.endswith('/linksdata'): @@ -16777,7 +16795,8 @@ class PubServer(BaseHTTPRequestHandler): pageNumber = \ self._receiveNewPost(currPostType, self.path, callingDomain, cookie, - authorized) + authorized, + self.server.contentLicenseUrl) if pageNumber: print(currPostType + ' post received') nickname = self.path.split('/users/')[1] diff --git a/desktop_client.py b/desktop_client.py index 93603f5ca..054f8b835 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -419,6 +419,7 @@ def _desktopReplyToPost(session, postId: str, screenreader: str, systemLanguage: str, espeak, conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str, signingPrivateKeyPem: str) -> None: """Use the desktop client to send a reply to the most recent post """ @@ -473,6 +474,7 @@ def _desktopReplyToPost(session, postId: str, attachedImageDescription, city, cachedWebfingers, personCache, isArticle, systemLanguage, lowBandwidth, + contentLicenseUrl, debug, postId, postId, conversationId, subject) == 0: sayStr = 'Reply sent' @@ -488,6 +490,7 @@ def _desktopNewPost(session, debug: bool, screenreader: str, systemLanguage: str, espeak, lowBandwidth: bool, + contentLicenseUrl: str, signingPrivateKeyPem: str) -> None: """Use the desktop client to create a new post """ @@ -538,6 +541,7 @@ def _desktopNewPost(session, attachedImageDescription, city, cachedWebfingers, personCache, isArticle, systemLanguage, lowBandwidth, + contentLicenseUrl, debug, None, None, conversationId, subject) == 0: sayStr = 'Post sent' @@ -1124,6 +1128,7 @@ def _desktopNewDM(session, toHandle: str, debug: bool, screenreader: str, systemLanguage: str, espeak, lowBandwidth: bool, + contentLicenseUrl: str, signingPrivateKeyPem: str) -> None: """Use the desktop client to create a new direct message which can include multiple destination handles @@ -1146,6 +1151,7 @@ def _desktopNewDM(session, toHandle: str, debug, screenreader, systemLanguage, espeak, lowBandwidth, + contentLicenseUrl, signingPrivateKeyPem) @@ -1156,6 +1162,7 @@ def _desktopNewDMbase(session, toHandle: str, debug: bool, screenreader: str, systemLanguage: str, espeak, lowBandwidth: bool, + contentLicenseUrl: str, signingPrivateKeyPem: str) -> None: """Use the desktop client to create a new direct message """ @@ -1246,6 +1253,7 @@ def _desktopNewDMbase(session, toHandle: str, attachedImageDescription, city, cachedWebfingers, personCache, isArticle, systemLanguage, lowBandwidth, + contentLicenseUrl, debug, None, None, conversationId, subject) == 0: sayStr = 'Direct message sent' @@ -1319,6 +1327,8 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, # TODO: this should probably be retrieved somehow from the server signingPrivateKeyPem = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' + blockedCache = {} indent = ' ' @@ -1716,6 +1726,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, screenreader, systemLanguage, espeak, conversationId, lowBandwidth, + contentLicenseUrl, signingPrivateKeyPem) refreshTimeline = True print('') @@ -1751,6 +1762,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, debug, screenreader, systemLanguage, espeak, lowBandwidth, + contentLicenseUrl, signingPrivateKeyPem) refreshTimeline = True else: @@ -1762,6 +1774,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, debug, screenreader, systemLanguage, espeak, lowBandwidth, + contentLicenseUrl, signingPrivateKeyPem) refreshTimeline = True print('') diff --git a/epicyon.py b/epicyon.py index 6cfe1768f..9cf52179e 100644 --- a/epicyon.py +++ b/epicyon.py @@ -1284,7 +1284,8 @@ if args.message: args.commentsEnabled, attach, mediaType, attachedImageDescription, city, cachedWebfingers, personCache, isArticle, - args.language, args.lowBandwidth, args.debug, + args.language, args.lowBandwidth, + args.contentLicenseUrl, args.debug, replyTo, replyTo, args.conversationId, subject) for i in range(10): # TODO detect send success/fail @@ -2333,7 +2334,8 @@ if args.avatar: sys.exit() city = 'London, England' if setProfileImage(baseDir, httpPrefix, args.nickname, domain, - port, args.avatar, 'avatar', '128x128', city): + port, args.avatar, 'avatar', '128x128', city, + args.contentLicenseUrl): print('Avatar added for ' + args.nickname) else: print('Avatar was not added for ' + args.nickname) @@ -2349,7 +2351,7 @@ if args.backgroundImage: city = 'London, England' if setProfileImage(baseDir, httpPrefix, args.nickname, domain, port, args.backgroundImage, 'background', - '256x256', city): + '256x256', city, args.contentLicenseUrl): print('Background image added for ' + args.nickname) else: print('Background image was not added for ' + args.nickname) @@ -2719,7 +2721,8 @@ if args.testdata: "mechanical", "City", "0", "GBP", "2 months", - debug, city, args.language, {}, 'shares', args.lowBandwidth) + debug, city, args.language, {}, 'shares', args.lowBandwidth, + args.contentLicenseUrl) addShare(baseDir, httpPrefix, nickname, domain, port, "witch hat", @@ -2729,7 +2732,8 @@ if args.testdata: "clothing", "City", "0", "GBP", "3 months", - debug, city, args.language, {}, 'shares', args.lowBandwidth) + debug, city, args.language, {}, 'shares', args.lowBandwidth, + args.contentLicenseUrl) deleteAllPosts(baseDir, nickname, domain, 'inbox') deleteAllPosts(baseDir, nickname, domain, 'outbox') @@ -2765,7 +2769,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "Zoiks!!!", testFollowersOnly, @@ -2778,7 +2782,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "Hey scoob we need like a hundred more #milkshakes", testFollowersOnly, @@ -2791,7 +2795,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "Getting kinda spooky around here", testFollowersOnly, @@ -2804,7 +2808,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "And they would have gotten away with it too" + "if it wasn't for those pesky hackers", @@ -2818,7 +2822,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "man these centralized sites are like the worst!", testFollowersOnly, @@ -2831,7 +2835,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "another mystery solved #test", testFollowersOnly, @@ -2844,7 +2848,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) createPublicPost(baseDir, nickname, domain, port, httpPrefix, "let's go bowling", testFollowersOnly, @@ -2857,7 +2861,7 @@ if args.testdata: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, args.language, conversationId, - lowBandwidth) + lowBandwidth, args.contentLicenseUrl) domainFull = domain + ':' + str(port) clearFollows(baseDir, nickname, domain) followPerson(baseDir, nickname, domain, 'maxboardroom', domainFull, diff --git a/inbox.py b/inbox.py index 0d336a0c0..fab4fca6e 100644 --- a/inbox.py +++ b/inbox.py @@ -2374,7 +2374,8 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str, cachedWebfingers: {}, personCache: {}, translate: {}, debug: bool, lastBounceMessage: [], systemLanguage: str, - signingPrivateKeyPem: str) -> bool: + signingPrivateKeyPem: str, + contentLicenseUrl: str) -> bool: """Sends a bounce message back to the sending handle if a DM has been rejected """ @@ -2433,7 +2434,8 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str, inReplyTo, inReplyToAtomUri, subject, debug, schedulePost, eventDate, eventTime, location, - systemLanguage, conversationId, lowBandwidth) + systemLanguage, conversationId, lowBandwidth, + contentLicenseUrl) if not postJsonObject: print('WARN: unable to create bounce message to ' + sendingHandle) return False @@ -2459,7 +2461,8 @@ def _isValidDM(baseDir: str, nickname: str, domain: str, port: int, translate: {}, debug: bool, lastBounceMessage: [], handle: str, systemLanguage: str, - signingPrivateKeyPem: str) -> bool: + signingPrivateKeyPem: str, + contentLicenseUrl: str) -> bool: """Is the given message a valid DM? """ if nickname == 'inbox': @@ -2537,7 +2540,8 @@ def _isValidDM(baseDir: str, nickname: str, domain: str, port: int, translate, debug, lastBounceMessage, systemLanguage, - signingPrivateKeyPem) + signingPrivateKeyPem, + contentLicenseUrl) return False # dm index will be updated @@ -2772,7 +2776,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, maxLikeCount: int, signingPrivateKeyPem: str, defaultReplyIntervalHours: int, - CWlists: {}, listsEnabled: str) -> bool: + CWlists: {}, listsEnabled: str, + contentLicenseUrl: str) -> bool: """ Anything which needs to be done after initial checks have passed """ actor = keyId @@ -3004,7 +3009,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, translate, debug, lastBounceMessage, handle, systemLanguage, - signingPrivateKeyPem): + signingPrivateKeyPem, + contentLicenseUrl): return False # get the actor being replied to @@ -3786,6 +3792,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, saveJson(queueJson['post'], sharedInboxPostFilename) listsEnabled = getConfigParam(baseDir, "listsEnabled") + contentLicenseUrl = getConfigParam(baseDir, "contentLicenseUrl") # for posts addressed to specific accounts for handle, capsId in recipientsDict.items(): @@ -3818,7 +3825,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, maxLikeCount, signingPrivateKeyPem, defaultReplyIntervalHours, - CWlists, listsEnabled) + CWlists, listsEnabled, + contentLicenseUrl) if debug: pprint(queueJson['post']) print('Queue: Queue post accepted') diff --git a/media.py b/media.py index c05faca93..184c8d2af 100644 --- a/media.py +++ b/media.py @@ -107,7 +107,8 @@ def _removeMetaData(imageFilename: str, outputFilename: str) -> None: def _spoofMetaData(baseDir: str, nickname: str, domain: str, - outputFilename: str, spoofCity: str) -> None: + outputFilename: str, spoofCity: str, + contentLicenseUrl: str) -> None: """Spoof image metadata using a decoy model for a given city """ if not os.path.isfile(outputFilename): @@ -151,6 +152,7 @@ def _spoofMetaData(baseDir: str, nickname: str, domain: str, '-GPSLongitude=' + str(longitude) + ' ' + '-GPSLatitudeRef=' + latitudeRef + ' ' + '-GPSLatitude=' + str(latitude) + ' ' + + '-copyright="' + contentLicenseUrl + '" ' + '-Comment="" ' + outputFilename) != 0: # nosec print('ERROR: exiftool failed to run') @@ -203,7 +205,7 @@ def convertImageToLowBandwidth(imageFilename: str) -> None: def processMetaData(baseDir: str, nickname: str, domain: str, imageFilename: str, outputFilename: str, - city: str) -> None: + city: str, contentLicenseUrl: str) -> None: """Handles image metadata. This tries to spoof the metadata if possible, but otherwise just removes it """ @@ -211,7 +213,8 @@ def processMetaData(baseDir: str, nickname: str, domain: str, _removeMetaData(imageFilename, outputFilename) # now add some spoofed data to misdirect surveillance capitalists - _spoofMetaData(baseDir, nickname, domain, outputFilename, city) + _spoofMetaData(baseDir, nickname, domain, outputFilename, city, + contentLicenseUrl) def _isMedia(imageFilename: str) -> bool: @@ -299,7 +302,8 @@ def attachMedia(baseDir: str, httpPrefix: str, nickname: str, domain: str, port: int, postJson: {}, imageFilename: str, mediaType: str, description: str, - city: str, lowBandwidth: bool) -> {}: + city: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Attaches media to a json object post The description can be None """ @@ -357,7 +361,8 @@ def attachMedia(baseDir: str, httpPrefix: str, if lowBandwidth: convertImageToLowBandwidth(imageFilename) processMetaData(baseDir, nickname, domain, - imageFilename, mediaFilename, city) + imageFilename, mediaFilename, city, + contentLicenseUrl) else: copyfile(imageFilename, mediaFilename) _updateEtag(mediaFilename) diff --git a/newsdaemon.py b/newsdaemon.py index a83616cb8..80c69bbb8 100644 --- a/newsdaemon.py +++ b/newsdaemon.py @@ -530,7 +530,8 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str, maxMirroredArticles: int, allowLocalNetworkAccess: bool, systemLanguage: str, - lowBandwidth: bool) -> None: + lowBandwidth: bool, + contentLicenseUrl: str) -> None: """Converts rss items in a newswire into posts """ if not newswire: @@ -622,7 +623,8 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str, attachImageFilename, mediaType, imageDescription, city, rssTitle, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) if not blog: continue @@ -818,7 +820,8 @@ def runNewswireDaemon(baseDir: str, httpd, httpd.maxMirroredArticles, httpd.allowLocalNetworkAccess, httpd.systemLanguage, - httpd.lowBandwidth) + httpd.lowBandwidth, + httpd.contentLicenseUrl) print('Newswire feed converted to ActivityPub') if httpd.maxNewsPosts > 0: diff --git a/outbox.py b/outbox.py index 78c9f1cc9..6b0bc0583 100644 --- a/outbox.py +++ b/outbox.py @@ -197,7 +197,8 @@ def postMessageToOutbox(session, translate: {}, peertubeInstances: str, theme: str, maxLikeCount: int, maxRecentPosts: int, CWlists: {}, - listsEnabled: str) -> bool: + listsEnabled: str, + contentLicenseUrl: str) -> bool: """post is received by the outbox Client to server message post https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery @@ -607,7 +608,8 @@ def postMessageToOutbox(session, translate: {}, print('DEBUG: handle share uploads') outboxShareUpload(baseDir, httpPrefix, postToNickname, domain, port, messageJson, debug, city, - systemLanguage, translate, lowBandwidth) + systemLanguage, translate, lowBandwidth, + contentLicenseUrl) if debug: print('DEBUG: handle undo share uploads') diff --git a/person.py b/person.py index 79daa3158..3594dd849 100644 --- a/person.py +++ b/person.py @@ -88,7 +88,8 @@ def generateRSAKey() -> (str, str): def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str, port: int, imageFilename: str, imageType: str, - resolution: str, city: str) -> bool: + resolution: str, city: str, + contentLicenseUrl: str) -> bool: """Saves the given image file as an avatar or background image for the given person """ @@ -151,7 +152,8 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str, resolution + ' -quality 50 ' + profileFilename subprocess.call(cmd, shell=True) processMetaData(baseDir, nickname, domain, - profileFilename, profileFilename, city) + profileFilename, profileFilename, city, + contentLicenseUrl) return True return False diff --git a/posts.py b/posts.py index 01eca5505..38be89bd0 100644 --- a/posts.py +++ b/posts.py @@ -1064,7 +1064,8 @@ def _createPostS2S(baseDir: str, nickname: str, domain: str, port: int, mediaType: str, imageDescription: str, city: str, postObjectType: str, summary: str, inReplyToAtomUri: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Creates a new server-to-server post """ actorUrl = localActorUrl(httpPrefix, nickname, domain) @@ -1124,7 +1125,8 @@ def _createPostS2S(baseDir: str, nickname: str, domain: str, port: int, newPost['object'] = \ attachMedia(baseDir, httpPrefix, nickname, domain, port, newPost['object'], attachImageFilename, - mediaType, imageDescription, city, lowBandwidth) + mediaType, imageDescription, city, lowBandwidth, + contentLicenseUrl) return newPost @@ -1137,7 +1139,8 @@ def _createPostC2S(baseDir: str, nickname: str, domain: str, port: int, mediaType: str, imageDescription: str, city: str, postObjectType: str, summary: str, inReplyToAtomUri: str, systemLanguage: str, - conversationId: str, lowBandwidth: str) -> {}: + conversationId: str, lowBandwidth: str, + contentLicenseUrl: str) -> {}: """Creates a new client-to-server post """ domainFull = getFullDomain(domain, port) @@ -1187,7 +1190,8 @@ def _createPostC2S(baseDir: str, nickname: str, domain: str, port: int, newPost = \ attachMedia(baseDir, httpPrefix, nickname, domain, port, newPost, attachImageFilename, - mediaType, imageDescription, city, lowBandwidth) + mediaType, imageDescription, city, lowBandwidth, + contentLicenseUrl) return newPost @@ -1314,7 +1318,8 @@ def _createPostBase(baseDir: str, anonymousParticipationEnabled: bool, eventStatus: str, ticketUrl: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Creates a message """ content = removeInvalidChars(content) @@ -1439,7 +1444,8 @@ def _createPostBase(baseDir: str, mediaType, imageDescription, city, postObjectType, summary, inReplyToAtomUri, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) else: newPost = \ _createPostC2S(baseDir, nickname, domain, port, @@ -1451,7 +1457,8 @@ def _createPostBase(baseDir: str, mediaType, imageDescription, city, postObjectType, summary, inReplyToAtomUri, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) _createPostMentions(ccUrl, newPost, toRecipients, tags) @@ -1685,7 +1692,8 @@ def createPublicPost(baseDir: str, location: str, isArticle: bool, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Public post """ domainFull = getFullDomain(domain, port) @@ -1716,7 +1724,8 @@ def createPublicPost(baseDir: str, repliesModerationOption, anonymousParticipationEnabled, eventStatus, ticketUrl, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) def _appendCitationsToBlogPost(baseDir: str, @@ -1759,7 +1768,8 @@ def createBlogPost(baseDir: str, subject: str, schedulePost: bool, eventDate: str, eventTime: str, location: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: blogJson = \ createPublicPost(baseDir, nickname, domain, port, httpPrefix, @@ -1771,7 +1781,7 @@ def createBlogPost(baseDir: str, schedulePost, eventDate, eventTime, location, True, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) blogJson['object']['url'] = \ blogJson['object']['url'].replace('/@', '/users/') _appendCitationsToBlogPost(baseDir, nickname, domain, blogJson) @@ -1785,7 +1795,8 @@ def createNewsPost(baseDir: str, attachImageFilename: str, mediaType: str, imageDescription: str, city: str, subject: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: clientToServer = False inReplyTo = None inReplyToAtomUri = None @@ -1804,7 +1815,7 @@ def createNewsPost(baseDir: str, schedulePost, eventDate, eventTime, location, True, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) blog['object']['type'] = 'Article' return blog @@ -1817,7 +1828,8 @@ def createQuestionPost(baseDir: str, attachImageFilename: str, mediaType: str, imageDescription: str, city: str, subject: str, durationDays: int, - systemLanguage: str, lowBandwidth: bool) -> {}: + systemLanguage: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Question post with multiple choice options """ domainFull = getFullDomain(domain, port) @@ -1834,7 +1846,7 @@ def createQuestionPost(baseDir: str, False, None, None, None, None, None, None, None, None, None, None, None, None, None, systemLanguage, - None, lowBandwidth) + None, lowBandwidth, contentLicenseUrl) messageJson['object']['type'] = 'Question' messageJson['object']['oneOf'] = [] messageJson['object']['votersCount'] = 0 @@ -1866,7 +1878,8 @@ def createUnlistedPost(baseDir: str, subject: str, schedulePost: bool, eventDate: str, eventTime: str, location: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Unlisted post. This has the #Public and followers links inverted. """ domainFull = getFullDomain(domain, port) @@ -1883,7 +1896,8 @@ def createUnlistedPost(baseDir: str, schedulePost, eventDate, eventTime, location, None, None, None, None, None, None, None, None, None, None, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) def createFollowersOnlyPost(baseDir: str, @@ -1899,7 +1913,8 @@ def createFollowersOnlyPost(baseDir: str, subject: str, schedulePost: bool, eventDate: str, eventTime: str, location: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Followers only post """ domainFull = getFullDomain(domain, port) @@ -1916,7 +1931,8 @@ def createFollowersOnlyPost(baseDir: str, schedulePost, eventDate, eventTime, location, None, None, None, None, None, None, None, None, None, None, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) def getMentionedPeople(baseDir: str, httpPrefix: str, @@ -1968,7 +1984,8 @@ def createDirectMessagePost(baseDir: str, schedulePost: bool, eventDate: str, eventTime: str, location: str, systemLanguage: str, - conversationId: str, lowBandwidth: bool) -> {}: + conversationId: str, lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Direct Message post """ content = resolvePetnames(baseDir, nickname, domain, content) @@ -1992,7 +2009,8 @@ def createDirectMessagePost(baseDir: str, schedulePost, eventDate, eventTime, location, None, None, None, None, None, None, None, None, None, None, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) # mentioned recipients go into To rather than Cc messageJson['to'] = messageJson['object']['cc'] messageJson['object']['to'] = messageJson['to'] @@ -2012,7 +2030,8 @@ def createReportPost(baseDir: str, attachImageFilename: str, mediaType: str, imageDescription: str, city: str, debug: bool, subject: str, systemLanguage: str, - lowBandwidth: bool) -> {}: + lowBandwidth: bool, + contentLicenseUrl: str) -> {}: """Send a report to moderators """ domainFull = getFullDomain(domain, port) @@ -2086,7 +2105,7 @@ def createReportPost(baseDir: str, False, None, None, None, None, None, None, None, None, None, None, None, None, None, systemLanguage, - None, lowBandwidth) + None, lowBandwidth, contentLicenseUrl) if not postJsonObject: continue @@ -2183,7 +2202,7 @@ def sendPost(signingPrivateKeyPem: str, projectVersion: str, isArticle: bool, systemLanguage: str, sharedItemsFederatedDomains: [], sharedItemFederationTokens: {}, - lowBandwidth: bool, + lowBandwidth: bool, contentLicenseUrl: str, debug: bool = False, inReplyTo: str = None, inReplyToAtomUri: str = None, subject: str = None) -> int: """Post to another inbox. Used by unit tests. @@ -2249,7 +2268,8 @@ def sendPost(signingPrivateKeyPem: str, projectVersion: str, False, None, None, None, None, None, None, None, None, None, None, None, None, None, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) # get the senders private key privateKeyPem = _getPersonKey(nickname, domain, baseDir, 'private') @@ -2331,6 +2351,7 @@ def sendPostViaServer(signingPrivateKeyPem: str, projectVersion: str, cachedWebfingers: {}, personCache: {}, isArticle: bool, systemLanguage: str, lowBandwidth: bool, + contentLicenseUrl: str, debug: bool = False, inReplyTo: str = None, inReplyToAtomUri: str = None, @@ -2416,7 +2437,8 @@ def sendPostViaServer(signingPrivateKeyPem: str, projectVersion: str, False, None, None, None, None, None, None, None, None, None, None, None, None, None, systemLanguage, - conversationId, lowBandwidth) + conversationId, lowBandwidth, + contentLicenseUrl) authHeader = createBasicAuthHeader(fromNickname, password) diff --git a/schedule.py b/schedule.py index b35d11f7a..804bc16b2 100644 --- a/schedule.py +++ b/schedule.py @@ -128,7 +128,8 @@ def _updatePostSchedule(baseDir: str, handle: str, httpd, httpd.maxLikeCount, httpd.maxRecentPosts, httpd.CWlists, - httpd.listsEnabled): + httpd.listsEnabled, + httpd.contentLicenseUrl): indexLines.remove(line) try: os.remove(postFilename) diff --git a/shares.py b/shares.py index a00e47458..9df356597 100644 --- a/shares.py +++ b/shares.py @@ -308,7 +308,8 @@ def addShare(baseDir: str, duration: str, debug: bool, city: str, price: str, currency: str, systemLanguage: str, translate: {}, - sharesFileType: str, lowBandwidth: bool) -> None: + sharesFileType: str, lowBandwidth: bool, + contentLicenseUrl: str) -> None: """Adds a new share """ if isFilteredGlobally(baseDir, @@ -363,7 +364,7 @@ def addShare(baseDir: str, convertImageToLowBandwidth(imageFilename) processMetaData(baseDir, nickname, domain, imageFilename, itemIDfile + '.' + ext, - city) + city, contentLicenseUrl) if moveImage: try: os.remove(imageFilename) @@ -1033,7 +1034,8 @@ def outboxShareUpload(baseDir: str, httpPrefix: str, nickname: str, domain: str, port: int, messageJson: {}, debug: bool, city: str, systemLanguage: str, translate: {}, - lowBandwidth: bool) -> None: + lowBandwidth: bool, + contentLicenseUrl: str) -> None: """ When a shared item is received by the outbox from c2s """ if not messageJson.get('type'): @@ -1095,7 +1097,7 @@ def outboxShareUpload(baseDir: str, httpPrefix: str, messageJson['object']['itemPrice'], messageJson['object']['itemCurrency'], systemLanguage, translate, 'shares', - lowBandwidth) + lowBandwidth, contentLicenseUrl) if debug: print('DEBUG: shared item received via c2s') diff --git a/tests.py b/tests.py index 39fe63547..616389903 100644 --- a/tests.py +++ b/tests.py @@ -753,6 +753,7 @@ def createServerAlice(path: str, domain: str, port: int, testLocation = None testIsArticle = False conversationId = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' createPublicPost(path, nickname, domain, port, httpPrefix, "No wise fish would go anywhere without a porpoise", testFollowersOnly, @@ -766,7 +767,7 @@ def createServerAlice(path: str, domain: str, port: int, testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) createPublicPost(path, nickname, domain, port, httpPrefix, "Curiouser and curiouser!", testFollowersOnly, @@ -780,7 +781,7 @@ def createServerAlice(path: str, domain: str, port: int, testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) createPublicPost(path, nickname, domain, port, httpPrefix, "In the gardens of memory, in the palace " + "of dreams, that is where you and I shall meet", @@ -795,7 +796,7 @@ def createServerAlice(path: str, domain: str, port: int, testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) regenerateIndexForBox(path, nickname, domain, 'outbox') global testServerAliceRunning testServerAliceRunning = True @@ -818,7 +819,7 @@ def createServerAlice(path: str, domain: str, port: int, maxLikeCount = 10 defaultReplyIntervalHours = 9999999999 listsEnabled = '' - contentLicenseUrl = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' print('Server running: Alice') runDaemon(contentLicenseUrl, listsEnabled, defaultReplyIntervalHours, @@ -894,6 +895,7 @@ def createServerBob(path: str, domain: str, port: int, testLocation = None testIsArticle = False conversationId = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' createPublicPost(path, nickname, domain, port, httpPrefix, "It's your life, live it your way.", testFollowersOnly, @@ -907,7 +909,7 @@ def createServerBob(path: str, domain: str, port: int, testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) createPublicPost(path, nickname, domain, port, httpPrefix, "One of the things I've realised is that " + "I am very simple", @@ -922,7 +924,7 @@ def createServerBob(path: str, domain: str, port: int, testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) createPublicPost(path, nickname, domain, port, httpPrefix, "Quantum physics is a bit of a passion of mine", testFollowersOnly, @@ -936,7 +938,7 @@ def createServerBob(path: str, domain: str, port: int, testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) regenerateIndexForBox(path, nickname, domain, 'outbox') global testServerBobRunning testServerBobRunning = True @@ -959,7 +961,7 @@ def createServerBob(path: str, domain: str, port: int, maxLikeCount = 10 defaultReplyIntervalHours = 9999999999 listsEnabled = '' - contentLicenseUrl = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' print('Server running: Bob') runDaemon(contentLicenseUrl, listsEnabled, defaultReplyIntervalHours, @@ -1029,7 +1031,7 @@ def createServerEve(path: str, domain: str, port: int, federationList: [], lowBandwidth = True defaultReplyIntervalHours = 9999999999 listsEnabled = '' - contentLicenseUrl = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' print('Server running: Eve') runDaemon(contentLicenseUrl, listsEnabled, defaultReplyIntervalHours, @@ -1101,7 +1103,7 @@ def createServerGroup(path: str, domain: str, port: int, lowBandwidth = True defaultReplyIntervalHours = 9999999999 listsEnabled = '' - contentLicenseUrl = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' print('Server running: Group') runDaemon(contentLicenseUrl, listsEnabled, defaultReplyIntervalHours, @@ -1140,6 +1142,7 @@ def testPostMessageBetweenServers(baseDir: str) -> None: systemLanguage = 'en' httpPrefix = 'http' proxyType = None + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' if os.path.isdir(baseDir + '/.tests'): shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None) @@ -1243,6 +1246,7 @@ def testPostMessageBetweenServers(baseDir: str) -> None: alicePersonCache, isArticle, systemLanguage, aliceSharedItemsFederatedDomains, aliceSharedItemFederationTokens, lowBandwidth, + contentLicenseUrl, inReplyTo, inReplyToAtomUri, subject) print('sendResult: ' + str(sendResult)) @@ -1441,6 +1445,7 @@ def testFollowBetweenServers(baseDir: str) -> None: httpPrefix = 'http' proxyType = None federationList = [] + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' if os.path.isdir(baseDir + '/.tests'): shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None) @@ -1580,6 +1585,7 @@ def testFollowBetweenServers(baseDir: str) -> None: alicePersonCache, isArticle, systemLanguage, aliceSharedItemsFederatedDomains, aliceSharedItemFederationTokens, lowBandwidth, + contentLicenseUrl, inReplyTo, inReplyToAtomUri, subject) print('sendResult: ' + str(sendResult)) @@ -1628,6 +1634,7 @@ def testSharedItemsFederation(baseDir: str) -> None: httpPrefix = 'http' proxyType = None federationList = [] + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' if os.path.isdir(baseDir + '/.tests'): shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None) @@ -1928,7 +1935,8 @@ def testSharedItemsFederation(baseDir: str) -> None: aliceSendThreads, alicePostLog, aliceCachedWebfingers, alicePersonCache, isArticle, systemLanguage, aliceSharedItemsFederatedDomains, - aliceSharedItemFederationTokens, lowBandwidth, True, + aliceSharedItemFederationTokens, lowBandwidth, + contentLicenseUrl, True, inReplyTo, inReplyToAtomUri, subject) print('sendResult: ' + str(sendResult)) @@ -2032,6 +2040,7 @@ def testGroupFollow(baseDir: str) -> None: httpPrefix = 'http' proxyType = None federationList = [] + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' if os.path.isdir(baseDir + '/.tests'): shutil.rmtree(baseDir + '/.tests', ignore_errors=False, onerror=None) @@ -2348,6 +2357,7 @@ def testGroupFollow(baseDir: str) -> None: alicePersonCache, isArticle, systemLanguage, aliceSharedItemsFederatedDomains, aliceSharedItemFederationTokens, lowBandwidth, + contentLicenseUrl, inReplyTo, inReplyToAtomUri, subject) print('sendResult: ' + str(sendResult)) @@ -2700,6 +2710,7 @@ def _testCreatePerson(baseDir: str): mediaType = None conversationId = None lowBandwidth = True + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' createPublicPost(baseDir, nickname, domain, port, httpPrefix, content, followersOnly, saveToFile, clientToServer, commentsEnabled, attachImageFilename, mediaType, @@ -2708,7 +2719,7 @@ def _testCreatePerson(baseDir: str): testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) os.chdir(currDir) shutil.rmtree(baseDir, ignore_errors=False, onerror=None) @@ -2771,6 +2782,7 @@ def testClientToServer(baseDir: str): global testServerAliceRunning global testServerBobRunning + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' testServerAliceRunning = False testServerBobRunning = False @@ -2887,6 +2899,7 @@ def testClientToServer(baseDir: str): attachedImageDescription, city, cachedWebfingers, personCache, isArticle, systemLanguage, lowBandwidth, + contentLicenseUrl, True, None, None, conversationId, None) print('sendResult: ' + str(sendResult)) @@ -4193,6 +4206,7 @@ def _testReplyToPublicPost(baseDir: str) -> None: testIsArticle = False conversationId = None lowBandwidth = True + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' reply = \ createPublicPost(baseDir, nickname, domain, port, httpPrefix, content, followersOnly, saveToFile, @@ -4203,7 +4217,7 @@ def _testReplyToPublicPost(baseDir: str) -> None: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) # print(str(reply)) assert reply['object']['content'] == \ '

' + \ @@ -4725,6 +4739,7 @@ def _testLinksWithinPost(baseDir: str) -> None: testIsArticle = False conversationId = None lowBandwidth = True + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' postJsonObject = \ createPublicPost(baseDir, nickname, domain, port, httpPrefix, @@ -4736,7 +4751,7 @@ def _testLinksWithinPost(baseDir: str) -> None: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) assert postJsonObject['object']['content'] == \ '

This is a test post with links.

' + \ @@ -4773,7 +4788,7 @@ def _testLinksWithinPost(baseDir: str) -> None: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) assert postJsonObject['object']['content'] == content assert postJsonObject['object']['contentMap'][systemLanguage] == content @@ -5711,6 +5726,7 @@ def _testCanReplyTo(baseDir: str) -> None: testIsArticle = False conversationId = None lowBandwidth = True + contentLicenseUrl = 'https://creativecommons.org/licenses/by/4.0' postJsonObject = \ createPublicPost(baseDir, nickname, domain, port, httpPrefix, @@ -5722,7 +5738,7 @@ def _testCanReplyTo(baseDir: str) -> None: testSubject, testSchedulePost, testEventDate, testEventTime, testLocation, testIsArticle, systemLanguage, conversationId, - lowBandwidth) + lowBandwidth, contentLicenseUrl) # set the date on the post currDateStr = "2021-09-08T20:45:00Z" postJsonObject['published'] = currDateStr