diff --git a/blocking.py b/blocking.py index 5c70ca676..67952d27b 100644 --- a/blocking.py +++ b/blocking.py @@ -874,3 +874,94 @@ def brochModeLapses(baseDir: str, lapseDays: int = 7) -> bool: print('Broch mode has elapsed') return True return False + + +def loadCWLists(baseDir: str, verbose: bool) -> {}: + """Load lists used for content warnings + """ + if not os.path.isdir(baseDir + '/cwlists'): + return {} + result = {} + for subdir, dirs, files in os.walk(baseDir + '/cwlists'): + for f in files: + if not f.endswith('.json'): + continue + listFilename = os.path.join(baseDir + '/cwlists', f) + print('listFilename: ' + listFilename) + listJson = loadJson(listFilename, 0, 1) + if not listJson: + continue + if not listJson.get('name'): + continue + if not listJson.get('words') and not listJson.get('domains'): + continue + name = listJson['name'] + if verbose: + print('List: ' + name) + result[name] = listJson + return result + + +def addCWfromLists(postJsonObject: {}, CWlists: {}, translate: {}, + listsEnabled: str) -> None: + """Adds content warnings by matching the post content + against domains or keywords + """ + if not listsEnabled: + return + if not postJsonObject['object'].get('content'): + return + cw = '' + if postJsonObject['object'].get('summary'): + cw = postJsonObject['object']['summary'] + + content = postJsonObject['object']['content'] + for name, item in CWlists.items(): + if name not in listsEnabled: + continue + if not item.get('warning'): + continue + warning = item['warning'] + + # is there a translated version of the warning? + if translate.get(warning): + warning = translate[warning] + + # is the warning already in the CW? + if warning in cw: + continue + + matched = False + + # match domains within the content + if item.get('domains'): + for domain in item['domains']: + if domain in content: + if cw: + cw = warning + ' / ' + cw + else: + cw = warning + matched = True + break + + if matched: + continue + + # match words within the content + if item.get('words'): + for wordStr in item['words']: + if wordStr in content: + if cw: + cw = warning + ' / ' + cw + else: + cw = warning + break + if cw: + postJsonObject['object']['summary'] = cw + postJsonObject['object']['sensitive'] = True + + +def getCWlistVariable(listName: str) -> str: + """Returns the variable associated with a CW list + """ + return 'list' + listName.replace(' ', '').replace("'", '') diff --git a/cwlists/murdoch.json b/cwlists/murdoch.json new file mode 100644 index 000000000..38932207d --- /dev/null +++ b/cwlists/murdoch.json @@ -0,0 +1,82 @@ +{ + "name": "Murdoch press", + "warning": "Murdoch Press", + "words": [], + "domains": [ + "api.news", + "content.api.news", + "newscdn.com.au", + "resourcesssl.newscdn.com.au", + "thesun.co.uk", + "thetimes.co.uk", + "thesundaytimes.co.uk", + "pressassociation.com", + "news.co.uk", + "newscorpaustralia.com", + "theaustralian.com.au", + "aap.com.au", + "news.com.au", + "skynews.com.au", + "skyweather.com.au", + "australiannewschannel.com.au", + "weeklytimesnow.com.au", + "dailytelegraph.com.au", + "heraldsun.com.au", + "geelongadvertiser.com.au", + "couriermail.com.au", + "thesundaymail.com.au", + "goldcoastbulletin.com.au", + "cairnspost.com.au", + "townsvillebulletin.com.au", + "adelaidenow.com.au", + "themercury.com.au", + "ntnews.com.au", + "postcourier.com.pg", + "nypost.com", + "pagesix.com", + "realtor.com", + "wsj.com", + "wsj.net", + "foxnews.com", + "fncstatic.com", + "foxnewsgo.com", + "fox.com", + "foxbusiness.com", + "foxsports.com", + "fssta.com", + "foxsports.com.au", + "dowjones.com", + "factiva.com", + "barrons.com", + "marketwatch.com", + "heatst.com", + "fnlondon.com", + "mansionglobal.com", + "spindices.com", + "spglobal.com", + "talksport.com", + "harpercollins.com", + "bestrecipes.com.au", + "hipages.com.au", + "homeimprovementpages.com.au", + "odds.com.au", + "onebigswitch.com.au", + "suddenly.com.au", + "supercoach.com.au", + "punters.com.au", + "kayosports.com.au", + "foxtel.com.au", + "newscorp.com", + "storyful.com", + "vogue.com.au", + "taste.com.au", + "kidspot.com.au", + "bodyandsoul.com.au", + "realcommercial.com.au", + "reastatic.net", + "realestate.com.au", + "whereilive.com.au", + "www.newsoftheworld.co.uk", + "newsoftheworld.co.uk" + ] +} diff --git a/cwlists/ukrwthinktanks.json b/cwlists/ukrwthinktanks.json new file mode 100644 index 000000000..b674ff49b --- /dev/null +++ b/cwlists/ukrwthinktanks.json @@ -0,0 +1,24 @@ +{ + "name": "UK RW Think Tanks", + "warning": "UK RW Think Tank", + "words": [ + "Adam Smith Institute", + "Bow Group", + "Centre for Policy Studies", + "Centre for Social Justice", + "Chatham House", + "Institute of Economic Affairs", + "Legatum Institute", + "Policy Exchange" + ], + "domains": [ + "adamsmith.org", + "bowgroup.org", + "cps.org.uk", + "centreforsocialjustice.org.uk", + "chathamhouse.org", + "iea.org.uk", + "https://li.com", + "policyexchange.org.uk" + ] +} diff --git a/daemon.py b/daemon.py index 5c6849af2..9bbbf2c09 100644 --- a/daemon.py +++ b/daemon.py @@ -125,6 +125,8 @@ from media import replaceTwitter from media import attachMedia from media import pathIsVideo from media import pathIsAudio +from blocking import getCWlistVariable +from blocking import loadCWLists from blocking import updateBlockedCache from blocking import mutePost from blocking import unmutePost @@ -1229,7 +1231,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.peertubeInstances, self.server.themeName, self.server.maxLikeCount, - self.server.maxRecentPosts) + self.server.maxRecentPosts, + self.server.CWlists, + self.server.listsEnabled) def _postToOutboxThread(self, messageJson: {}) -> bool: """Creates a thread to send a post @@ -3007,7 +3011,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if hashtagStr: msg = hashtagStr.encode('utf-8') msglen = len(msg) @@ -3065,7 +3071,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, 'outbox', self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if historyStr: msg = historyStr.encode('utf-8') msglen = len(msg) @@ -3103,7 +3111,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, 'bookmarks', self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if bookmarksStr: msg = bookmarksStr.encode('utf-8') msglen = len(msg) @@ -3207,7 +3217,9 @@ class PubServer(BaseHTTPRequestHandler): accessKeys, self.server.systemLanguage, self.server.maxLikeCount, - signingPrivateKeyPem) + signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if profileStr: msg = profileStr.encode('utf-8') msglen = len(msg) @@ -5684,9 +5696,24 @@ class PubServer(BaseHTTPRequestHandler): except BaseException: pass - # save blocked user agents - # This is admin lebel and global to the instance - if path.startswith('/users/' + adminNickname + '/'): + if isModerator(self.server.baseDir, nickname): + # set selected content warning lists + newListsEnabled = '' + for name, item in self.server.CWlists.items(): + listVarName = getCWlistVariable(name) + if fields.get(listVarName): + if fields[listVarName] == 'on': + if newListsEnabled: + newListsEnabled += ', ' + name + else: + newListsEnabled += name + if newListsEnabled != self.server.listsEnabled: + self.server.listsEnabled = newListsEnabled + setConfigParam(self.server.baseDir, + "listsEnabled", + newListsEnabled) + + # save blocked user agents userAgentsBlocked = [] if fields.get('userAgentsBlockedStr'): userAgentsBlockedStr = \ @@ -6727,7 +6754,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if hashtagStr: msg = hashtagStr.encode('utf-8') msglen = len(msg) @@ -6854,9 +6883,6 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(actorPathStr, cookie, callingDomain) return - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton1', - self.server.debug) if not self.server.session: print('Starting new session during repeat button') self.server.session = createSession(proxyType) @@ -6866,9 +6892,6 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton2', - self.server.debug) self.server.actorRepeat = path.split('?actor=')[1] announceToStr = \ localActorUrl(httpPrefix, self.postToNickname, domainFull) + \ @@ -6891,9 +6914,6 @@ class PubServer(BaseHTTPRequestHandler): debug, self.server.projectVersion, self.server.signingPrivateKeyPem) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton3', - self.server.debug) announceFilename = None if announceJson: # save the announce straight to the outbox @@ -6905,10 +6925,6 @@ class PubServer(BaseHTTPRequestHandler): self.postToNickname, domainFull, announceJson, 'outbox') - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton4', - self.server.debug) - # clear the icon from the cache so that it gets updated if self.server.iconsCache.get('repeat.png'): del self.server.iconsCache['repeat.png'] @@ -6917,7 +6933,7 @@ class PubServer(BaseHTTPRequestHandler): self._postToOutboxThread(announceJson) fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton5', + '_GET', '_announceButton postToOutboxThread', self.server.debug) # generate the html for the announce @@ -6927,9 +6943,6 @@ class PubServer(BaseHTTPRequestHandler): cachedPostFilename = \ getCachedPostFilename(baseDir, self.postToNickname, domain, announceJson) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton6', - self.server.debug) if debug: print('Announced post json: ' + str(announceJson)) print('Announced post nickname: ' + @@ -6940,9 +6953,6 @@ class PubServer(BaseHTTPRequestHandler): followerApprovalActive(baseDir, self.postToNickname, domain) showRepeats = not isDM(announceJson) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton7', - self.server.debug) individualPostAsHtml(self.server.signingPrivateKeyPem, False, self.server.recentPostsCache, self.server.maxRecentPosts, @@ -6968,10 +6978,9 @@ class PubServer(BaseHTTPRequestHandler): showRepeats, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_announceButton8', - self.server.debug) + False, True, False, + self.server.CWlists, + self.server.listsEnabled) self.server.GETbusy = False actorAbsolute = self._getInstanceUrl(callingDomain) + actor @@ -7348,9 +7357,6 @@ class PubServer(BaseHTTPRequestHandler): self._redirect_headers(actorPathStr, cookie, callingDomain) return - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton1', - self.server.debug) if not self.server.session: print('Starting new session during like') self.server.session = createSession(proxyType) @@ -7359,9 +7365,6 @@ class PubServer(BaseHTTPRequestHandler): self._404() self.server.GETbusy = False return - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton2', - self.server.debug) likeActor = \ localActorUrl(httpPrefix, self.postToNickname, domainFull) actorLiked = path.split('?actor=')[1] @@ -7372,9 +7375,6 @@ class PubServer(BaseHTTPRequestHandler): origActor, origPostUrl, origFilename = \ getOriginalPostFromAnnounceUrl(likeUrl, baseDir, self.postToNickname, domain) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton3', - self.server.debug) likeUrl2 = likeUrl likedPostFilename = origFilename if origActor and origPostUrl: @@ -7394,7 +7394,7 @@ class PubServer(BaseHTTPRequestHandler): self._postToOutbox(likeJson, self.server.projectVersion, None) fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton4', + '_GET', '_likeButton postToOutbox', self.server.debug) print('Locating liked post ' + likeUrl) @@ -7403,9 +7403,6 @@ class PubServer(BaseHTTPRequestHandler): likedPostFilename = \ locatePost(baseDir, self.postToNickname, domain, likeUrl) if likedPostFilename: - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton5', - self.server.debug) recentPostsCache = self.server.recentPostsCache likedPostJson = loadJson(likedPostFilename, 0, 1) if origFilename and origPostUrl: @@ -7417,9 +7414,6 @@ class PubServer(BaseHTTPRequestHandler): likedPostFilename = origFilename if debug: print('Updating likes for ' + likedPostFilename) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton6', - self.server.debug) updateLikesCollection(recentPostsCache, baseDir, likedPostFilename, likeUrl, likeActor, self.postToNickname, domain, @@ -7428,9 +7422,6 @@ class PubServer(BaseHTTPRequestHandler): print('Regenerating html post for changed likes collection') # clear the icon from the cache so that it gets updated if likedPostJson: - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton6', - self.server.debug) cachedPostFilename = \ getCachedPostFilename(baseDir, self.postToNickname, domain, likedPostJson) @@ -7444,9 +7435,6 @@ class PubServer(BaseHTTPRequestHandler): followerApprovalActive(baseDir, self.postToNickname, domain) showRepeats = not isDM(likedPostJson) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton7', - self.server.debug) individualPostAsHtml(self.server.signingPrivateKeyPem, False, self.server.recentPostsCache, self.server.maxRecentPosts, @@ -7473,10 +7461,9 @@ class PubServer(BaseHTTPRequestHandler): showRepeats, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) - fitnessPerformance(GETstartTime, self.server.fitness, - '_GET', '_likeButton8', - self.server.debug) + False, True, False, + self.server.CWlists, + self.server.listsEnabled) else: print('WARN: Liked post not found: ' + likedPostFilename) # clear the icon from the cache so that it gets updated @@ -7636,7 +7623,9 @@ class PubServer(BaseHTTPRequestHandler): showRepeats, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, + self.server.CWlists, + self.server.listsEnabled) else: print('WARN: Unliked post not found: ' + likedPostFilename) # clear the icon from the cache so that it gets updated @@ -7771,7 +7760,9 @@ class PubServer(BaseHTTPRequestHandler): showRepeats, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, + self.server.CWlists, + self.server.listsEnabled) else: print('WARN: Bookmarked post not found: ' + bookmarkFilename) # self._postToOutbox(bookmarkJson, self.server.projectVersion, None) @@ -7905,7 +7896,9 @@ class PubServer(BaseHTTPRequestHandler): showRepeats, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, + self.server.CWlists, + self.server.listsEnabled) else: print('WARN: Unbookmarked post not found: ' + bookmarkFilename) self.server.GETbusy = False @@ -8007,7 +8000,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if deleteStr: deleteStrLen = len(deleteStr) self._set_headers('text/html', deleteStrLen, @@ -8115,7 +8110,9 @@ class PubServer(BaseHTTPRequestHandler): showIndividualPostIcons, manuallyApproveFollowers, showPublicOnly, storeToCache, - useCacheOnly) + useCacheOnly, + self.server.CWlists, + self.server.listsEnabled) else: print('WARN: Muted post not found: ' + muteFilename) @@ -8224,7 +8221,9 @@ class PubServer(BaseHTTPRequestHandler): showIndividualPostIcons, manuallyApproveFollowers, showPublicOnly, storeToCache, - useCacheOnly) + useCacheOnly, + self.server.CWlists, + self.server.listsEnabled) else: print('WARN: Unmuted post not found: ' + muteFilename) self.server.GETbusy = False @@ -8347,7 +8346,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8446,7 +8447,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8555,7 +8558,8 @@ class PubServer(BaseHTTPRequestHandler): self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, rolesList, - None, None) + None, None, self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8668,7 +8672,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.maxLikeCount, sharedItemsFederatedDomains, skills, - None, None) + None, None, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -8817,7 +8823,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.themeName, self.server.systemLanguage, self.server.maxLikeCount, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9063,7 +9071,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) if GETstartTime: fitnessPerformance(GETstartTime, self.server.fitness, @@ -9211,7 +9221,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9352,7 +9364,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9492,7 +9506,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9632,7 +9648,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9781,7 +9799,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -9928,7 +9948,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10034,7 +10056,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10118,7 +10142,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10239,7 +10265,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10377,7 +10405,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10506,7 +10536,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, sharedItemsFederatedDomains, - self.server.signingPrivateKeyPem) + self.server.signingPrivateKeyPem, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10633,7 +10665,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, shares, - pageNumber, sharesPerPage) + pageNumber, sharesPerPage, + self.server.CWlists, + self.server.listsEnabled) msg = msg.encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, @@ -10757,7 +10791,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.sharedItemsFederatedDomains, following, pageNumber, - followsPerPage).encode('utf-8') + followsPerPage, + self.server.CWlists, + self.server.listsEnabled).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain, False) @@ -10880,7 +10916,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.sharedItemsFederatedDomains, followers, pageNumber, - followsPerPage).encode('utf-8') + followsPerPage, + self.server.CWlists, + self.server.listsEnabled).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain, False) @@ -11019,7 +11057,9 @@ class PubServer(BaseHTTPRequestHandler): self.server.systemLanguage, self.server.maxLikeCount, self.server.sharedItemsFederatedDomains, - None, None).encode('utf-8') + None, None, None, + self.server.CWlists, + self.server.listsEnabled).encode('utf-8') msglen = len(msg) self._set_headers('text/html', msglen, cookie, callingDomain, False) @@ -11785,7 +11825,9 @@ class PubServer(BaseHTTPRequestHandler): city, self.server.userAgentsBlocked, accessKeys, - defaultReplyIntervalHours).encode('utf-8') + defaultReplyIntervalHours, + self.server.CWlists, + self.server.listsEnabled).encode('utf-8') if msg: msglen = len(msg) self._set_headers('text/html', msglen, @@ -16875,7 +16917,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None: break -def runDaemon(defaultReplyIntervalHours: int, +def runDaemon(listsEnabled: str, + defaultReplyIntervalHours: int, lowBandwidth: bool, maxLikeCount: int, sharedItemsFederatedDomains: [], @@ -17228,6 +17271,13 @@ def runDaemon(defaultReplyIntervalHours: int, if not os.path.isdir(baseDir + '/accounts/news@' + domain): print('Creating news inbox: news@' + domain) createNewsInbox(baseDir, domain, port, httpPrefix) + setConfigParam(baseDir, "listsEnabled", "Murdoch press") + + if listsEnabled: + httpd.listsEnabled = listsEnabled + else: + httpd.listsEnabled = getConfigParam(baseDir, "listsEnabled") + httpd.CWlists = loadCWLists(baseDir, True) # set the avatar for the news account httpd.themeName = getConfigParam(baseDir, 'theme') @@ -17359,7 +17409,8 @@ def runDaemon(defaultReplyIntervalHours: int, httpd.systemLanguage, httpd.maxLikeCount, httpd.signingPrivateKeyPem, - httpd.defaultReplyIntervalHours), daemon=True) + httpd.defaultReplyIntervalHours, + httpd.CWlists), daemon=True) print('Creating scheduled post thread') httpd.thrPostSchedule = \ diff --git a/epicyon.py b/epicyon.py index 897ddafa3..e9f39e100 100644 --- a/epicyon.py +++ b/epicyon.py @@ -112,6 +112,10 @@ def str2bool(v) -> bool: parser = argparse.ArgumentParser(description='ActivityPub Server') +parser.add_argument('--listsEnabled', type=str, + default=None, + help='Names of content warning lists enabled. ' + + 'See the cwlists directory') parser.add_argument('--userAgentBlocks', type=str, default=None, help='List of blocked user agents, separated by commas') @@ -3011,6 +3015,13 @@ if userAgentsBlockedStr: for agentBlockStr in agentBlocksList: userAgentsBlocked.append(agentBlockStr.strip()) +listsEnabled = '' +if args.listsEnabled: + listsEnabled = args.listsEnabled + setConfigParam(baseDir, 'listsEnabled', listsEnabled) +else: + listsEnabled = getConfigParam(baseDir, 'listsEnabled') + city = \ getConfigParam(baseDir, 'city') if city is not None: @@ -3064,7 +3075,8 @@ if args.defaultCurrency: print('Default currency set to ' + args.defaultCurrency) if __name__ == "__main__": - runDaemon(args.defaultReplyIntervalHours, + runDaemon(listsEnabled, + args.defaultReplyIntervalHours, args.lowBandwidth, args.maxLikeCount, sharedItemsFederatedDomains, userAgentsBlocked, diff --git a/fitnessFunctions.py b/fitnessFunctions.py index 1a4bb1976..f3531e7aa 100644 --- a/fitnessFunctions.py +++ b/fitnessFunctions.py @@ -112,7 +112,7 @@ def htmlWatchPointsGraph(baseDir: str, fitness: {}, fitnessId: str, htmlStr += \ '\n' + \ ' ' + name + '\n' + \ - ' ' + str(timeMS) + 'mS\n' + \ + ' ' + str(timeMS) + '\n' + \ '\n' ctr += 1 if ctr >= maxEntries: diff --git a/inbox.py b/inbox.py index 47dd760aa..8df064200 100644 --- a/inbox.py +++ b/inbox.py @@ -274,7 +274,9 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> None: + signingPrivateKeyPem: str, + CWlists: {}, + listsEnabled: str) -> None: """Converts the json post into html and stores it in a cache This enables the post to be quickly displayed later """ @@ -298,7 +300,8 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, maxLikeCount, - notDM, True, True, False, True, False) + notDM, True, True, False, True, False, + CWlists, listsEnabled) def validInbox(baseDir: str, nickname: str, domain: str) -> bool: @@ -980,7 +983,8 @@ def _receiveLike(recentPostsCache: {}, peertubeInstances: [], allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, - maxLikeCount: int) -> bool: + maxLikeCount: int, CWlists: {}, + listsEnabled: str) -> bool: """Receives a Like activity within the POST section of HTTPServer """ if messageJson['type'] != 'Like': @@ -1082,7 +1086,8 @@ def _receiveLike(recentPostsCache: {}, maxLikeCount, notDM, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, CWlists, + listsEnabled) return True @@ -1100,7 +1105,8 @@ def _receiveUndoLike(recentPostsCache: {}, peertubeInstances: [], allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, - maxLikeCount: int) -> bool: + maxLikeCount: int, CWlists: {}, + listsEnabled: str) -> bool: """Receives an undo like activity within the POST section of HTTPServer """ if messageJson['type'] != 'Undo': @@ -1191,7 +1197,8 @@ def _receiveUndoLike(recentPostsCache: {}, maxLikeCount, notDM, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, CWlists, + listsEnabled) return True @@ -1208,7 +1215,8 @@ def _receiveBookmark(recentPostsCache: {}, peertubeInstances: [], allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, - maxLikeCount: int) -> bool: + maxLikeCount: int, CWlists: {}, + listsEnabled: {}) -> bool: """Receives a bookmark activity within the POST section of HTTPServer """ if not messageJson.get('type'): @@ -1299,7 +1307,8 @@ def _receiveBookmark(recentPostsCache: {}, maxLikeCount, notDM, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, CWlists, + listsEnabled) return True @@ -1316,7 +1325,8 @@ def _receiveUndoBookmark(recentPostsCache: {}, peertubeInstances: [], allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, - maxLikeCount: int) -> bool: + maxLikeCount: int, CWlists: {}, + listsEnabled: str) -> bool: """Receives an undo bookmark activity within the POST section of HTTPServer """ if not messageJson.get('type'): @@ -1408,7 +1418,7 @@ def _receiveUndoBookmark(recentPostsCache: {}, maxLikeCount, notDM, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, CWlists, listsEnabled) return True @@ -1502,7 +1512,8 @@ def _receiveAnnounce(recentPostsCache: {}, maxRecentPosts: int, allowDeletion: bool, peertubeInstances: [], - maxLikeCount: int) -> bool: + maxLikeCount: int, CWlists: {}, + listsEnabled: str) -> bool: """Receives an announce activity within the POST section of HTTPServer """ if messageJson['type'] != 'Announce': @@ -1614,7 +1625,8 @@ def _receiveAnnounce(recentPostsCache: {}, maxLikeCount, notDM, showIndividualPostIcons, manuallyApproveFollowers, - False, True, False) + False, True, False, CWlists, + listsEnabled) if not announceHtml: print('WARN: Unable to generate html for announce ' + str(messageJson)) @@ -2551,7 +2563,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, themeName: str, systemLanguage: str, maxLikeCount: int, signingPrivateKeyPem: str, - defaultReplyIntervalHours: int) -> bool: + defaultReplyIntervalHours: int, + CWlists: {}, listsEnabled: str) -> bool: """ Anything which needs to be done after initial checks have passed """ actor = keyId @@ -2581,7 +2594,7 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, - maxLikeCount): + maxLikeCount, CWlists, listsEnabled): if debug: print('DEBUG: Like accepted from ' + actor) return False @@ -2603,7 +2616,7 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, - maxLikeCount): + maxLikeCount, CWlists, listsEnabled): if debug: print('DEBUG: Undo like accepted from ' + actor) return False @@ -2625,7 +2638,7 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, - maxLikeCount): + maxLikeCount, CWlists, listsEnabled): if debug: print('DEBUG: Bookmark accepted from ' + actor) return False @@ -2647,7 +2660,7 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, - maxLikeCount): + maxLikeCount, CWlists, listsEnabled): if debug: print('DEBUG: Undo bookmark accepted from ' + actor) return False @@ -2673,7 +2686,7 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, maxRecentPosts, allowDeletion, peertubeInstances, - maxLikeCount): + maxLikeCount, CWlists, listsEnabled): if debug: print('DEBUG: Announce accepted from ' + actor) @@ -2954,7 +2967,8 @@ def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, allowLocalNetworkAccess, themeName, systemLanguage, maxLikeCount, - signingPrivateKeyPem) + signingPrivateKeyPem, + CWlists, listsEnabled) if debug: timeDiff = \ str(int((time.time() - htmlCacheStartTime) * @@ -3239,7 +3253,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, verifyAllSignatures: bool, themeName: str, systemLanguage: str, maxLikeCount: int, signingPrivateKeyPem: str, - defaultReplyIntervalHours: int) -> None: + defaultReplyIntervalHours: int, + CWlists: {}) -> None: """Processes received items and moves them to the appropriate directories """ @@ -3626,6 +3641,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, if not os.path.isfile(sharedInboxPostFilename): saveJson(queueJson['post'], sharedInboxPostFilename) + listsEnabled = getConfigParam(baseDir, "listsEnabled") + # for posts addressed to specific accounts for handle, capsId in recipientsDict.items(): destination = \ @@ -3656,7 +3673,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, themeName, systemLanguage, maxLikeCount, signingPrivateKeyPem, - defaultReplyIntervalHours) + defaultReplyIntervalHours, + CWlists, listsEnabled) if debug: pprint(queueJson['post']) print('Queue: Queue post accepted') diff --git a/outbox.py b/outbox.py index 20c719db6..522f7a402 100644 --- a/outbox.py +++ b/outbox.py @@ -196,7 +196,8 @@ def postMessageToOutbox(session, translate: {}, signingPrivateKeyPem: str, peertubeInstances: str, theme: str, maxLikeCount: int, - maxRecentPosts: int) -> bool: + maxRecentPosts: int, CWlists: {}, + listsEnabled: str) -> bool: """post is received by the outbox Client to server message post https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery @@ -467,7 +468,8 @@ def postMessageToOutbox(session, translate: {}, boxNameIndex != 'dm', showIndividualPostIcons, manuallyApproveFollowers, - False, True, useCacheOnly) + False, True, useCacheOnly, + CWlists, listsEnabled) if outboxAnnounce(recentPostsCache, baseDir, messageJson, debug): diff --git a/schedule.py b/schedule.py index 112bbfeef..09212396c 100644 --- a/schedule.py +++ b/schedule.py @@ -124,7 +124,9 @@ def _updatePostSchedule(baseDir: str, handle: str, httpd, httpd.peertubeInstances, httpd.themeName, httpd.maxLikeCount, - httpd.maxRecentPosts): + httpd.maxRecentPosts, + httpd.CWlists, + httpd.listsEnabled): indexLines.remove(line) try: os.remove(postFilename) diff --git a/tests.py b/tests.py index 126ddb5ea..f1182cb06 100644 --- a/tests.py +++ b/tests.py @@ -164,6 +164,8 @@ from shares import updateSharedItemFederationToken from shares import mergeSharedItemTokens from shares import sendShareViaServer from shares import getSharedItemsCatalogViaServer +from blocking import loadCWLists +from blocking import addCWfromLists testServerGroupRunning = False testServerAliceRunning = False @@ -815,8 +817,9 @@ def createServerAlice(path: str, domain: str, port: int, userAgentsBlocked = [] maxLikeCount = 10 defaultReplyIntervalHours = 9999999999 + listsEnabled = '' print('Server running: Alice') - runDaemon(defaultReplyIntervalHours, + runDaemon(listsEnabled, defaultReplyIntervalHours, lowBandwidth, maxLikeCount, sharedItemsFederatedDomains, userAgentsBlocked, @@ -953,8 +956,9 @@ def createServerBob(path: str, domain: str, port: int, userAgentsBlocked = [] maxLikeCount = 10 defaultReplyIntervalHours = 9999999999 + listsEnabled = '' print('Server running: Bob') - runDaemon(defaultReplyIntervalHours, + runDaemon(listsEnabled, defaultReplyIntervalHours, lowBandwidth, maxLikeCount, sharedItemsFederatedDomains, userAgentsBlocked, @@ -1020,8 +1024,9 @@ def createServerEve(path: str, domain: str, port: int, federationList: [], maxLikeCount = 10 lowBandwidth = True defaultReplyIntervalHours = 9999999999 + listsEnabled = '' print('Server running: Eve') - runDaemon(defaultReplyIntervalHours, + runDaemon(listsEnabled, defaultReplyIntervalHours, lowBandwidth, maxLikeCount, sharedItemsFederatedDomains, userAgentsBlocked, @@ -1089,8 +1094,9 @@ def createServerGroup(path: str, domain: str, port: int, maxLikeCount = 10 lowBandwidth = True defaultReplyIntervalHours = 9999999999 + listsEnabled = '' print('Server running: Group') - runDaemon(defaultReplyIntervalHours, + runDaemon(listsEnabled, defaultReplyIntervalHours, lowBandwidth, maxLikeCount, sharedItemsFederatedDomains, userAgentsBlocked, @@ -5764,6 +5770,46 @@ def _testWordsSimilarity() -> None: assert similarity > 80 +def _testAddCWfromLists(baseDir: str) -> None: + print('testAddCWfromLists') + translate = {} + CWlists = loadCWLists(baseDir, True) + assert CWlists + + postJsonObject = { + "object": { + "sensitive": False, + "summary": None, + "content": "" + } + } + addCWfromLists(postJsonObject, CWlists, translate, 'Murdoch press') + assert postJsonObject['object']['sensitive'] is False + assert postJsonObject['object']['summary'] is None + + postJsonObject = { + "object": { + "sensitive": False, + "summary": None, + "content": "Blah blah news.co.uk blah blah" + } + } + addCWfromLists(postJsonObject, CWlists, translate, 'Murdoch press') + assert postJsonObject['object']['sensitive'] is True + assert postJsonObject['object']['summary'] == "Murdoch Press" + + postJsonObject = { + "object": { + "sensitive": True, + "summary": "Existing CW", + "content": "Blah blah news.co.uk blah blah" + } + } + addCWfromLists(postJsonObject, CWlists, translate, 'Murdoch press') + assert postJsonObject['object']['sensitive'] is True + assert postJsonObject['object']['summary'] == "Murdoch Press / Existing CW" + + def runAllTests(): baseDir = os.getcwd() print('Running tests...') @@ -5771,6 +5817,7 @@ def runAllTests(): _translateOntology(baseDir) _testGetPriceFromString() _testFunctions() + _testAddCWfromLists(baseDir) _testWordsSimilarity() _testSecondsBetweenPublished() _testSignAndVerify() diff --git a/translations/ar.json b/translations/ar.json index 325f09dc4..2ae899465 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -488,5 +488,6 @@ "Members": "أعضاء", "Join": "انضم", "Leave": "يترك", - "System Monitor": "مراقب النظام" + "System Monitor": "مراقب النظام", + "Add content warnings for the following sites": "أضف تحذيرات المحتوى للمواقع التالية" } diff --git a/translations/ca.json b/translations/ca.json index 8e7b37c08..f4861d724 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -488,5 +488,6 @@ "Members": "Membres", "Join": "Uneix-te", "Leave": "Marxa", - "System Monitor": "Monitor del sistema" + "System Monitor": "Monitor del sistema", + "Add content warnings for the following sites": "Afegiu advertiments de contingut per als llocs següents" } diff --git a/translations/cy.json b/translations/cy.json index 97daf5510..f25c5a27c 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -488,5 +488,6 @@ "Members": "Aelodau", "Join": "Ymunwch", "Leave": "Gadewch", - "System Monitor": "Monitor System" + "System Monitor": "Monitor System", + "Add content warnings for the following sites": "Ychwanegwch rybuddion cynnwys ar gyfer y gwefannau canlynol" } diff --git a/translations/de.json b/translations/de.json index 0667373c2..e2760a864 100644 --- a/translations/de.json +++ b/translations/de.json @@ -488,5 +488,6 @@ "Members": "Mitglieder", "Join": "Verbinden", "Leave": "Verlassen", - "System Monitor": "Systemmonitor" + "System Monitor": "Systemmonitor", + "Add content warnings for the following sites": "Inhaltswarnungen für die folgenden Websites hinzufügen" } diff --git a/translations/en.json b/translations/en.json index d7b71a414..4e8d3ec13 100644 --- a/translations/en.json +++ b/translations/en.json @@ -488,5 +488,6 @@ "Members": "Members", "Join": "Join", "Leave": "Leave", - "System Monitor": "System Monitor" + "System Monitor": "System Monitor", + "Add content warnings for the following sites": "Add content warnings for the following sites" } diff --git a/translations/es.json b/translations/es.json index 1bd72c84e..67cf33835 100644 --- a/translations/es.json +++ b/translations/es.json @@ -488,5 +488,6 @@ "Members": "Miembros", "Join": "Entrar", "Leave": "Dejar", - "System Monitor": "Monitor del sistema" + "System Monitor": "Monitor del sistema", + "Add content warnings for the following sites": "Agregue advertencias de contenido para los siguientes sitios" } diff --git a/translations/fr.json b/translations/fr.json index 16f396e53..056a914c0 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -488,5 +488,6 @@ "Members": "Membres", "Join": "Rejoindre", "Leave": "Laisser", - "System Monitor": "Moniteur système" + "System Monitor": "Moniteur système", + "Add content warnings for the following sites": "Ajouter des avertissements de contenu pour les sites suivants" } diff --git a/translations/ga.json b/translations/ga.json index eb0b12af3..73f740bcf 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -488,5 +488,6 @@ "Members": "Baill", "Join": "Bí páirteach", "Leave": "Fág", - "System Monitor": "Monatóir Córais" + "System Monitor": "Monatóir Córais", + "Add content warnings for the following sites": "Cuir rabhaidh ábhair leis na suíomhanna seo a leanas" } diff --git a/translations/hi.json b/translations/hi.json index b93a3180d..c4e475f2d 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -488,5 +488,6 @@ "Members": "सदस्यों", "Join": "शामिल हों", "Leave": "छोड़ना", - "System Monitor": "सिस्टम मॉनिटर" + "System Monitor": "सिस्टम मॉनिटर", + "Add content warnings for the following sites": "निम्नलिखित साइटों के लिए सामग्री चेतावनियाँ जोड़ें" } diff --git a/translations/it.json b/translations/it.json index 4ea931172..4648aedae 100644 --- a/translations/it.json +++ b/translations/it.json @@ -488,5 +488,6 @@ "Members": "Membri", "Join": "Aderire", "Leave": "Lasciare", - "System Monitor": "Monitor di sistema" + "System Monitor": "Monitor di sistema", + "Add content warnings for the following sites": "Aggiungi avvisi sui contenuti per i seguenti siti" } diff --git a/translations/ja.json b/translations/ja.json index d751c83aa..0fe46e4f4 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -488,5 +488,6 @@ "Members": "メンバー", "Join": "加入", "Leave": "離れる", - "System Monitor": "システムモニター" + "System Monitor": "システムモニター", + "Add content warnings for the following sites": "次のサイトのコンテンツ警告を追加します" } diff --git a/translations/ku.json b/translations/ku.json index bf383bdfe..1c4f7dd19 100644 --- a/translations/ku.json +++ b/translations/ku.json @@ -488,5 +488,6 @@ "Members": "Endam", "Join": "Bihevgirêdan", "Leave": "Terikandin", - "System Monitor": "System Monitor" + "System Monitor": "System Monitor", + "Add content warnings for the following sites": "Ji bo malperên jêrîn hişyariyên naverokê zêde bikin" } diff --git a/translations/oc.json b/translations/oc.json index c2e6f0c8f..d898dfa43 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -484,5 +484,6 @@ "Members": "Members", "Join": "Join", "Leave": "Leave", - "System Monitor": "System Monitor" + "System Monitor": "System Monitor", + "Add content warnings for the following sites": "Add content warnings for the following sites" } diff --git a/translations/pt.json b/translations/pt.json index 75444a1b5..789df52ea 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -488,5 +488,6 @@ "Members": "Membros", "Join": "Juntar", "Leave": "Sair", - "System Monitor": "Monitor de Sistema" + "System Monitor": "Monitor de Sistema", + "Add content warnings for the following sites": "Adicione avisos de conteúdo para os seguintes sites" } diff --git a/translations/ru.json b/translations/ru.json index 83597b5b0..2352871d7 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -488,5 +488,6 @@ "Members": "Члены", "Join": "Присоединиться", "Leave": "Оставлять", - "System Monitor": "Системный монитор" + "System Monitor": "Системный монитор", + "Add content warnings for the following sites": "Добавить предупреждения о содержании для следующих сайтов" } diff --git a/translations/sw.json b/translations/sw.json index c658897b2..3e7aa7b8d 100644 --- a/translations/sw.json +++ b/translations/sw.json @@ -488,5 +488,6 @@ "Members": "Wanachama", "Join": "Jiunge", "Leave": "Ondoka", - "System Monitor": "Ufuatiliaji wa Mfumo" + "System Monitor": "Ufuatiliaji wa Mfumo", + "Add content warnings for the following sites": "Ongeza maonyo ya yaliyomo kwa wavuti zifuatazo" } diff --git a/translations/zh.json b/translations/zh.json index db16066e8..e7104146b 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -488,5 +488,6 @@ "Members": "会员", "Join": "加入", "Leave": "离开", - "System Monitor": "系统监视器" + "System Monitor": "系统监视器", + "Add content warnings for the following sites": "为以下网站添加内容警告" } diff --git a/webapp_confirm.py b/webapp_confirm.py index b24ce5422..a2b29250d 100644 --- a/webapp_confirm.py +++ b/webapp_confirm.py @@ -35,7 +35,8 @@ def htmlConfirmDelete(cssCache: {}, peertubeInstances: [], allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, - maxLikeCount: int, signingPrivateKeyPem: str) -> str: + maxLikeCount: int, signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Shows a screen asking to confirm the deletion of a post """ if '/statuses/' not in messageId: @@ -79,7 +80,8 @@ def htmlConfirmDelete(cssCache: {}, showPublishedDateOnly, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, maxLikeCount, - False, False, False, False, False, False) + False, False, False, False, False, False, + CWlists, listsEnabled) deletePostStr += '
' deletePostStr += \ '

' + \ diff --git a/webapp_frontscreen.py b/webapp_frontscreen.py index 8462d80e2..25104840a 100644 --- a/webapp_frontscreen.py +++ b/webapp_frontscreen.py @@ -35,7 +35,8 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, CWlists: {}, + listsEnabled: str) -> str: """Shows posts on the front screen of a news instance These should only be public blog posts from the features timeline which is the blog timeline of the news actor @@ -81,7 +82,8 @@ def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, themeName, systemLanguage, maxLikeCount, False, False, False, - True, False, False) + True, False, False, + CWlists, listsEnabled) if postStr: profileStr += postStr + separatorStr ctr += 1 @@ -109,9 +111,10 @@ def htmlFrontScreen(signingPrivateKeyPem: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - extraJson: {} = None, - pageNumber: int = None, - maxItemsPerPage: int = None) -> str: + extraJson: {}, + pageNumber: int, + maxItemsPerPage: int, + CWlists: {}, listsEnabled: str) -> str: """Show the news instance front screen """ nickname = profileJson['preferredUsername'] @@ -182,7 +185,8 @@ def htmlFrontScreen(signingPrivateKeyPem: str, allowLocalNetworkAccess, theme, systemLanguage, maxLikeCount, - signingPrivateKeyPem) + licenseStr + signingPrivateKeyPem, + CWlists, listsEnabled) + licenseStr # Footer which is only used for system accounts profileFooterStr = ' \n' diff --git a/webapp_moderation.py b/webapp_moderation.py index ef455e412..21009939a 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -52,7 +52,8 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the moderation feed as html This is what you see when selecting the "mod" timeline """ @@ -72,7 +73,7 @@ def htmlModeration(cssCache: {}, defaultTimeline: str, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, sharedItemsFederatedDomains, - signingPrivateKeyPem) + signingPrivateKeyPem, CWlists, listsEnabled) def htmlAccountInfo(cssCache: {}, translate: {}, diff --git a/webapp_post.py b/webapp_post.py index 4e5e6cbe6..74d90a6b1 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -77,6 +77,7 @@ from webfinger import webfingerHandle from speaker import updateSpeaker from languages import autoTranslatePost from blocking import isBlocked +from blocking import addCWfromLists def _logPostTiming(enableTimingLog: bool, postStartTime, debugId: str) -> None: @@ -1205,7 +1206,9 @@ def individualPostAsHtml(signingPrivateKeyPem: str, manuallyApprovesFollowers: bool, showPublicOnly: bool, storeToCache: bool, - useCacheOnly: bool) -> str: + useCacheOnly: bool, + CWlists: {}, + listsEnabled: str) -> str: """ Shows a single post as html """ if not postJsonObject: @@ -1651,6 +1654,9 @@ def individualPostAsHtml(signingPrivateKeyPem: str, if newFooterStr: footerStr = newFooterStr + # add any content warning from the cwlists directory + addCWfromLists(postJsonObject, CWlists, translate, listsEnabled) + postIsSensitive = False if postJsonObject['object'].get('sensitive'): # sensitive posts should have a summary @@ -1825,7 +1831,8 @@ def htmlIndividualPost(cssCache: {}, peertubeInstances: [], allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, - maxLikeCount: int, signingPrivateKeyPem: str) -> str: + maxLikeCount: int, signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show an individual post as html """ postStr = '' @@ -1878,7 +1885,8 @@ def htmlIndividualPost(cssCache: {}, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, maxLikeCount, - False, authorized, False, False, False, False) + False, authorized, False, False, False, False, + CWlists, listsEnabled) messageId = removeIdEnding(postJsonObject['id']) # show the previous posts @@ -1910,7 +1918,8 @@ def htmlIndividualPost(cssCache: {}, themeName, systemLanguage, maxLikeCount, False, authorized, - False, False, False, False) + postStr + False, False, False, False, + CWlists, listsEnabled) + postStr # show the following posts postFilename = locatePost(baseDir, nickname, domain, messageId) @@ -1944,7 +1953,8 @@ def htmlIndividualPost(cssCache: {}, themeName, systemLanguage, maxLikeCount, False, authorized, - False, False, False, False) + False, False, False, False, + CWlists, listsEnabled) cssFilename = baseDir + '/epicyon-profile.css' if os.path.isfile(baseDir + '/epicyon.css'): cssFilename = baseDir + '/epicyon.css' @@ -1968,7 +1978,8 @@ def htmlPostReplies(cssCache: {}, allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, CWlists: {}, + listsEnabled: str) -> str: """Show the replies to an individual post as html """ repliesStr = '' @@ -1991,7 +2002,8 @@ def htmlPostReplies(cssCache: {}, allowLocalNetworkAccess, themeName, systemLanguage, maxLikeCount, - False, False, False, False, False, False) + False, False, False, False, False, False, + CWlists, listsEnabled) cssFilename = baseDir + '/epicyon-profile.css' if os.path.isfile(baseDir + '/epicyon.css'): diff --git a/webapp_profile.py b/webapp_profile.py index 9de5871e4..914d212c8 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -34,6 +34,7 @@ from person import personBoxJson from person import getActorJson from person import getPersonAvatarUrl from webfinger import webfingerHandle +from posts import isModerator from posts import parseUserFeed from posts import getPersonBox from posts import isCreateInsideAnnounce @@ -69,6 +70,7 @@ from webapp_utils import endEditSection from blog import getBlogAddress from webapp_post import individualPostAsHtml from webapp_timeline import htmlIndividualShare +from blocking import getCWlistVariable def htmlProfileAfterSearch(cssCache: {}, @@ -89,7 +91,8 @@ def htmlProfileAfterSearch(cssCache: {}, accessKeys: {}, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show a profile page after a search for a fediverse address """ http = False @@ -306,7 +309,8 @@ def htmlProfileAfterSearch(cssCache: {}, peertubeInstances, allowLocalNetworkAccess, themeName, systemLanguage, maxLikeCount, - False, False, False, False, False, False) + False, False, False, False, False, False, + CWlists, listsEnabled) i += 1 if i >= 8: break @@ -516,8 +520,9 @@ def htmlProfile(signingPrivateKeyPem: str, debug: bool, accessKeys: {}, city: str, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - extraJson: {} = None, pageNumber: int = None, - maxItemsPerPage: int = None) -> str: + extraJson: {}, pageNumber: int, + maxItemsPerPage: int, + CWlists: {}, listsEnabled: str) -> str: """Show the profile page as html """ nickname = profileJson['preferredUsername'] @@ -539,8 +544,9 @@ def htmlProfile(signingPrivateKeyPem: str, newswire, theme, extraJson, allowLocalNetworkAccess, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, - pageNumber, maxItemsPerPage) + sharedItemsFederatedDomains, None, + pageNumber, maxItemsPerPage, CWlists, + listsEnabled) domain, port = getDomainFromActor(profileJson['id']) if not domain: @@ -897,7 +903,8 @@ def htmlProfile(signingPrivateKeyPem: str, allowLocalNetworkAccess, theme, systemLanguage, maxLikeCount, - signingPrivateKeyPem) + licenseStr + signingPrivateKeyPem, + CWlists, listsEnabled) + licenseStr if not isGroup: if selected == 'following': profileStr += \ @@ -963,7 +970,8 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Shows posts on the profile screen These should only be public posts """ @@ -1008,7 +1016,8 @@ def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, themeName, systemLanguage, maxLikeCount, False, False, False, - True, False, False) + True, False, False, + CWlists, listsEnabled) if postStr: profileStr += postStr + separatorStr ctr += 1 @@ -1512,7 +1521,8 @@ def _htmlEditProfileSharedItems(baseDir: str, nickname: str, domain: str, def _htmlEditProfileFiltering(baseDir: str, nickname: str, domain: str, userAgentsBlocked: str, translate: {}, - replyIntervalHours: int) -> str: + replyIntervalHours: int, + CWlists: {}, listsEnabled: str) -> str: """Filtering and blocking section of edit profile screen """ filterStr = '' @@ -1658,15 +1668,32 @@ def _htmlEditProfileFiltering(baseDir: str, nickname: str, domain: str, 'style="height:200px" spellcheck="false">' + \ allowedInstancesStr + '\n' - userAgentsBlockedStr = '' - for ua in userAgentsBlocked: - if userAgentsBlockedStr: - userAgentsBlockedStr += '\n' - userAgentsBlockedStr += ua - editProfileForm += \ - editTextArea(translate['Blocked User Agents'], - 'userAgentsBlockedStr', userAgentsBlockedStr, - 200, '', False) + if isModerator(baseDir, nickname): + userAgentsBlockedStr = '' + for ua in userAgentsBlocked: + if userAgentsBlockedStr: + userAgentsBlockedStr += '\n' + userAgentsBlockedStr += ua + editProfileForm += \ + editTextArea(translate['Blocked User Agents'], + 'userAgentsBlockedStr', userAgentsBlockedStr, + 200, '', False) + + CWlistsStr = '' + for name, item in CWlists.items(): + variableName = getCWlistVariable(name) + listIsEnabled = False + if listsEnabled: + if name in listsEnabled: + listIsEnabled = True + if translate.get(name): + name = translate[name] + CWlistsStr += editCheckBox(name, variableName, listIsEnabled) + if CWlistsStr: + idx = 'Add content warnings for the following sites' + editProfileForm += \ + '\n' + \ + '
' + CWlistsStr editProfileForm += endEditSection() return editProfileForm @@ -1950,7 +1977,8 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, textModeBanner: str, city: str, userAgentsBlocked: str, accessKeys: {}, - defaultReplyIntervalHours: int) -> str: + defaultReplyIntervalHours: int, + CWlists: {}, listsEnabled: str) -> str: """Shows the edit profile screen """ path = path.replace('/inbox', '').replace('/outbox', '') @@ -2146,7 +2174,8 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, editProfileForm += \ _htmlEditProfileFiltering(baseDir, nickname, domain, userAgentsBlocked, translate, - replyIntervalHours) + replyIntervalHours, + CWlists, listsEnabled) # git projects section editProfileForm += \ diff --git a/webapp_search.py b/webapp_search.py index c98f73c35..5c48ac6b3 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -598,7 +598,9 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str, themeName: str, boxName: str, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, + listsEnabled: str) -> str: """Show a page containing search results for your post history """ if historysearch.startswith("'"): @@ -683,7 +685,8 @@ def htmlHistorySearch(cssCache: {}, translate: {}, baseDir: str, themeName, systemLanguage, maxLikeCount, showIndividualPostIcons, showIndividualPostIcons, - False, False, False, False) + False, False, False, False, + CWlists, listsEnabled) if postStr: historySearchForm += separatorStr + postStr index += 1 @@ -707,7 +710,8 @@ def htmlHashtagSearch(cssCache: {}, allowLocalNetworkAccess: bool, themeName: str, systemLanguage: str, maxLikeCount: int, - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show a page containing search results for a hashtag or after selecting a hashtag from the swarm """ @@ -865,7 +869,8 @@ def htmlHashtagSearch(cssCache: {}, showRepeats, showIcons, manuallyApprovesFollowers, showPublicOnly, - storeToCache, False) + storeToCache, False, CWlists, + listsEnabled) if postStr: hashtagSearchForm += separatorStr + postStr index += 1 diff --git a/webapp_timeline.py b/webapp_timeline.py index 91afad775..27db4313b 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -446,7 +446,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the timeline as html """ enableTimingLog = False @@ -913,7 +914,8 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str, boxName != 'dm', showIndividualPostIcons, manuallyApproveFollowers, - False, True, useCacheOnly) + False, True, useCacheOnly, + CWlists, listsEnabled) _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '12') @@ -1137,7 +1139,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the shares timeline as html """ manuallyApproveFollowers = \ @@ -1162,7 +1165,8 @@ def htmlShares(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlWanted(cssCache: {}, defaultTimeline: str, @@ -1189,7 +1193,8 @@ def htmlWanted(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the wanted timeline as html """ manuallyApproveFollowers = \ @@ -1214,7 +1219,8 @@ def htmlWanted(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInbox(cssCache: {}, defaultTimeline: str, @@ -1242,7 +1248,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the inbox as html """ manuallyApproveFollowers = \ @@ -1267,7 +1274,8 @@ def htmlInbox(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlBookmarks(cssCache: {}, defaultTimeline: str, @@ -1295,7 +1303,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the bookmarks as html """ manuallyApproveFollowers = \ @@ -1320,7 +1329,8 @@ def htmlBookmarks(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInboxDMs(cssCache: {}, defaultTimeline: str, @@ -1348,7 +1358,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the DM timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1368,7 +1379,8 @@ def htmlInboxDMs(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInboxReplies(cssCache: {}, defaultTimeline: str, @@ -1396,7 +1408,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the replies timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1417,7 +1430,8 @@ def htmlInboxReplies(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInboxMedia(cssCache: {}, defaultTimeline: str, @@ -1445,7 +1459,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the media timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1466,7 +1481,8 @@ def htmlInboxMedia(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, @@ -1494,7 +1510,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the blogs timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1515,7 +1532,8 @@ def htmlInboxBlogs(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, @@ -1544,7 +1562,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the features timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1565,7 +1584,8 @@ def htmlInboxFeatures(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlInboxNews(cssCache: {}, defaultTimeline: str, @@ -1593,7 +1613,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the news timeline as html """ return htmlTimeline(cssCache, defaultTimeline, @@ -1614,7 +1635,8 @@ def htmlInboxNews(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled) def htmlOutbox(cssCache: {}, defaultTimeline: str, @@ -1642,7 +1664,8 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, accessKeys: {}, systemLanguage: str, maxLikeCount: int, sharedItemsFederatedDomains: [], - signingPrivateKeyPem: str) -> str: + signingPrivateKeyPem: str, + CWlists: {}, listsEnabled: str) -> str: """Show the Outbox as html """ manuallyApproveFollowers = \ @@ -1664,4 +1687,5 @@ def htmlOutbox(cssCache: {}, defaultTimeline: str, authorized, None, theme, peertubeInstances, allowLocalNetworkAccess, textModeBanner, accessKeys, systemLanguage, maxLikeCount, - sharedItemsFederatedDomains, signingPrivateKeyPem) + sharedItemsFederatedDomains, signingPrivateKeyPem, + CWlists, listsEnabled)