From ab5a871a2226c7f07b5dfccdd4429eee682e055a Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 09:51:55 +0000 Subject: [PATCH 01/88] Try switching cc and to --- daemon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index 6c76b5a2e..de0047836 100644 --- a/daemon.py +++ b/daemon.py @@ -4548,8 +4548,8 @@ class PubServer(BaseHTTPRequestHandler): 'id': actorJson['id'] + '#updates/' + pubNumber, 'type': 'Update', 'actor': actorJson['id'], - 'to': [pubStr], - 'cc': [actorJson['id'] + '/followers'], + 'cc': [pubStr], + 'to': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) From a15b2be343a44887ba6bd3eed3741b553f693905 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 10:43:19 +0000 Subject: [PATCH 02/88] Tidying --- daemon.py | 4 ++-- posts.py | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/daemon.py b/daemon.py index de0047836..6c76b5a2e 100644 --- a/daemon.py +++ b/daemon.py @@ -4548,8 +4548,8 @@ class PubServer(BaseHTTPRequestHandler): 'id': actorJson['id'] + '#updates/' + pubNumber, 'type': 'Update', 'actor': actorJson['id'], - 'cc': [pubStr], - 'to': [actorJson['id'] + '/followers'], + 'to': [pubStr], + 'cc': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) diff --git a/posts.py b/posts.py index aefd0564c..8338cd023 100644 --- a/posts.py +++ b/posts.py @@ -1174,7 +1174,7 @@ def postIsAddressedToFollowers(baseDir: str, postJsonObject: {}) -> bool: """Returns true if the given post is addressed to followers of the nickname """ - domain = getFullDomain(domain, port) + domainFull = getFullDomain(domain, port) if not postJsonObject.get('object'): return False @@ -1192,7 +1192,7 @@ def postIsAddressedToFollowers(baseDir: str, if postJsonObject.get('cc'): ccList = postJsonObject['cc'] - followersUrl = httpPrefix + '://' + domain + '/users/' + \ + followersUrl = httpPrefix + '://' + domainFull + '/users/' + \ nickname + '/followers' # does the followers url exist in 'to' or 'cc' lists? @@ -2353,6 +2353,26 @@ def hasSharedInbox(session, httpPrefix: str, domain: str) -> bool: return False +def sendingProfileUpdate(postJsonObject: {}) -> bool: + """Returns true if the given json is a profile update + """ + if postJsonObject['type'] != 'Update': + return False + if not postJsonObject.get('object'): + return False + if not isinstance(postJsonObject['object'], dict): + return False + if not postJsonObject['object'].get('type'): + return False + activityType = postJsonObject['object']['type'] + if activityType == 'Person' or \ + activityType == 'Application' or \ + activityType == 'Group' or \ + activityType == 'Service': + return True + return False + + def sendToFollowers(session, baseDir: str, nickname: str, domain: str, @@ -2438,18 +2458,10 @@ def sendToFollowers(session, baseDir: str, toNickname = 'inbox' if toNickname != 'inbox' and postJsonObject.get('type'): - if postJsonObject['type'] == 'Update': - if postJsonObject.get('object'): - if isinstance(postJsonObject['object'], dict): - if postJsonObject['object'].get('type'): - typ = postJsonObject['object']['type'] - if typ == 'Person' or \ - typ == 'Application' or \ - typ == 'Group' or \ - typ == 'Service': - print('Sending profile update to ' + - 'shared inbox of ' + toDomain) - toNickname = 'inbox' + if sendingProfileUpdate(postJsonObject): + print('Sending profile update to ' + + 'shared inbox of ' + toDomain) + toNickname = 'inbox' if debug: print('DEBUG: Sending from ' + nickname + '@' + domain + From d8d6751c2f68e79a2b7038f9fa13480a4b1967c0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 11:05:31 +0000 Subject: [PATCH 03/88] Try two ways of getting the shared inbox --- daemon.py | 2 +- posts.py | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/daemon.py b/daemon.py index 6c76b5a2e..321a313c6 100644 --- a/daemon.py +++ b/daemon.py @@ -4543,13 +4543,13 @@ class PubServer(BaseHTTPRequestHandler): # remove the context from the actor json and put it # at the start of the Upgrade activity del actorJson['@context'] + # NOTE: there is deliberately no cc here updateActorJson = { '@context': pubContext, 'id': actorJson['id'] + '#updates/' + pubNumber, 'type': 'Update', 'actor': actorJson['id'], 'to': [pubStr], - 'cc': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) diff --git a/posts.py b/posts.py index 8338cd023..705de387a 100644 --- a/posts.py +++ b/posts.py @@ -2342,14 +2342,20 @@ def sendToNamedAddresses(session, baseDir: str, def hasSharedInbox(session, httpPrefix: str, domain: str) -> bool: """Returns true if the given domain has a shared inbox + This tries the new and the old way of webfingering the shared inbox """ - wfRequest = webfingerHandle(session, domain + '@' + domain, - httpPrefix, {}, - None, __version__) - if wfRequest: - if isinstance(wfRequest, dict): - if not wfRequest.get('errors'): - return True + tryHandles = [ + domain + '@' + domain, + 'inbox@' + domain + ] + for handle in tryHandles: + wfRequest = webfingerHandle(session, handle, + httpPrefix, {}, + None, __version__) + if wfRequest: + if isinstance(wfRequest, dict): + if not wfRequest.get('errors'): + return True return False @@ -2424,8 +2430,8 @@ def sendToFollowers(session, baseDir: str, if debug: if withSharedInbox: print(followerDomain + ' has shared inbox') - else: - print(followerDomain + ' does not have a shared inbox') + if not withSharedInbox: + print(followerDomain + ' does not have a shared inbox') toPort = port index = 0 From ef72b93984711758b6941404158b9e88196ac087 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 11:11:52 +0000 Subject: [PATCH 04/88] Add followers --- daemon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index 321a313c6..6c76b5a2e 100644 --- a/daemon.py +++ b/daemon.py @@ -4543,13 +4543,13 @@ class PubServer(BaseHTTPRequestHandler): # remove the context from the actor json and put it # at the start of the Upgrade activity del actorJson['@context'] - # NOTE: there is deliberately no cc here updateActorJson = { '@context': pubContext, 'id': actorJson['id'] + '#updates/' + pubNumber, 'type': 'Update', 'actor': actorJson['id'], 'to': [pubStr], + 'cc': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) From 886e4f2beb285d0a97755fe322e7ebe1f41bdbda Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 11:48:00 +0000 Subject: [PATCH 05/88] Adjustable timeout for dormant post threads --- daemon.py | 14 ++++++++++---- epicyon.py | 13 ++++++++++++- tests.py | 12 +++++++++--- threads.py | 8 +++++--- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/daemon.py b/daemon.py index 6c76b5a2e..20dc14b85 100644 --- a/daemon.py +++ b/daemon.py @@ -12980,12 +12980,13 @@ class EpicyonServer(ThreadingHTTPServer): return HTTPServer.handle_error(self, request, client_address) -def runPostsQueue(baseDir: str, sendThreads: [], debug: bool) -> None: +def runPostsQueue(baseDir: str, sendThreads: [], debug: bool, + timeoutMins: int) -> None: """Manages the threads used to send posts """ while True: time.sleep(1) - removeDormantThreads(baseDir, sendThreads, debug) + removeDormantThreads(baseDir, sendThreads, debug, timeoutMins) def runSharesExpire(versionNumber: str, baseDir: str) -> None: @@ -13048,7 +13049,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None: break -def runDaemon(dormantMonths: int, +def runDaemon(sendThreadsTimeoutMins: int, + dormantMonths: int, maxNewswirePosts: int, allowLocalNetworkAccess: bool, maxFeedItemSizeKb: int, @@ -13343,10 +13345,14 @@ def runDaemon(dormantMonths: int, httpd.maxPostsInBox), daemon=True) httpd.thrCache.start() + # number of mins after which sending posts or updates will expire + httpd.sendThreadsTimeoutMins = sendThreadsTimeoutMins + print('Creating posts queue') httpd.thrPostsQueue = \ threadWithTrace(target=runPostsQueue, - args=(baseDir, httpd.sendThreads, debug), daemon=True) + args=(baseDir, httpd.sendThreads, debug, + httpd.sendThreadsTimeoutMins), daemon=True) if not unitTest: httpd.thrPostsWatchdog = \ threadWithTrace(target=runPostsWatchdog, diff --git a/epicyon.py b/epicyon.py index ba8eb64b3..8b243c66e 100644 --- a/epicyon.py +++ b/epicyon.py @@ -122,6 +122,11 @@ parser.add_argument('--dormantMonths', default=3, help='How many months does a followed account need to ' + 'be unseen for before being considered dormant') +parser.add_argument('--sendThreadsTimeoutMins', + dest='sendThreadsTimeoutMins', type=int, + default=30, + help='How many minutes before a thread to send out ' + + 'posts expires') parser.add_argument('--maxNewswirePosts', dest='maxNewswirePosts', type=int, default=20, @@ -2035,6 +2040,11 @@ dormantMonths = \ if dormantMonths is not None: args.dormantMonths = int(dormantMonths) +sendThreadsTimeoutMins = \ + getConfigParam(baseDir, 'sendThreadsTimeoutMins') +if sendThreadsTimeoutMins is not None: + args.sendThreadsTimeoutMins = int(sendThreadsTimeoutMins) + allowNewsFollowers = \ getConfigParam(baseDir, 'allowNewsFollowers') if allowNewsFollowers is not None: @@ -2083,7 +2093,8 @@ if setTheme(baseDir, themeName, domain, args.allowLocalNetworkAccess): print('Theme set to ' + themeName) if __name__ == "__main__": - runDaemon(args.dormantMonths, + runDaemon(args.sendThreadsTimeoutMins, + args.dormantMonths, args.maxNewswirePosts, args.allowLocalNetworkAccess, args.maxFeedItemSizeKb, diff --git a/tests.py b/tests.py index 654f977be..4b41b1fc4 100644 --- a/tests.py +++ b/tests.py @@ -296,8 +296,10 @@ def createServerAlice(path: str, domain: str, port: int, allowLocalNetworkAccess = True maxNewswirePosts = 20 dormantMonths = 3 + sendThreadsTimeoutMins = 30 print('Server running: Alice') - runDaemon(dormantMonths, maxNewswirePosts, + runDaemon(sendThreadsTimeoutMins, + dormantMonths, maxNewswirePosts, allowLocalNetworkAccess, 2048, False, True, False, False, True, 10, False, 0, 100, 1024, 5, False, @@ -366,8 +368,10 @@ def createServerBob(path: str, domain: str, port: int, allowLocalNetworkAccess = True maxNewswirePosts = 20 dormantMonths = 3 + sendThreadsTimeoutMins = 30 print('Server running: Bob') - runDaemon(dormantMonths, maxNewswirePosts, + runDaemon(sendThreadsTimeoutMins, + dormantMonths, maxNewswirePosts, allowLocalNetworkAccess, 2048, False, True, False, False, True, 10, False, 0, 100, 1024, 5, False, 0, @@ -410,8 +414,10 @@ def createServerEve(path: str, domain: str, port: int, federationList: [], allowLocalNetworkAccess = True maxNewswirePosts = 20 dormantMonths = 3 + sendThreadsTimeoutMins = 30 print('Server running: Eve') - runDaemon(dormantMonths, maxNewswirePosts, + runDaemon(sendThreadsTimeoutMins, + dormantMonths, maxNewswirePosts, allowLocalNetworkAccess, 2048, False, True, False, False, True, 10, False, 0, 100, 1024, 5, False, 0, diff --git a/threads.py b/threads.py index cdb3cb95d..89a43a1eb 100644 --- a/threads.py +++ b/threads.py @@ -69,12 +69,14 @@ class threadWithTrace(threading.Thread): daemon=True) -def removeDormantThreads(baseDir: str, threadsList: [], debug: bool) -> None: +def removeDormantThreads(baseDir: str, threadsList: [], debug: bool, + timeoutMins=30) -> None: """Removes threads whose execution has completed """ if len(threadsList) == 0: return + timeoutSecs = int(timeoutMins * 60) dormantThreads = [] currTime = datetime.datetime.utcnow() changed = False @@ -92,13 +94,13 @@ def removeDormantThreads(baseDir: str, threadsList: [], debug: bool) -> None: 'thread is not alive ten seconds after start') removeThread = True # timeout for started threads - if (currTime - th.startTime).total_seconds() > 600: + if (currTime - th.startTime).total_seconds() > timeoutSecs: if debug: print('DEBUG: started thread timed out') removeThread = True else: # timeout for threads which havn't been started - if (currTime - th.startTime).total_seconds() > 600: + if (currTime - th.startTime).total_seconds() > timeoutSecs: if debug: print('DEBUG: unstarted thread timed out') removeThread = True From 7ee5c89ff2879e65d27330ab1828bfc00d317496 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 11:54:14 +0000 Subject: [PATCH 06/88] Script to check sending updates --- scripts/checkupdate | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 scripts/checkupdate diff --git a/scripts/checkupdate b/scripts/checkupdate new file mode 100755 index 000000000..278a76fb1 --- /dev/null +++ b/scripts/checkupdate @@ -0,0 +1,2 @@ +#!/bin/bash +journalctl -u epicyon -r | grep "Sending profile update to\|a shared inbox" \ No newline at end of file From 3330ed1601cf77b52f946b978ae24b30168d71aa Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 13:04:51 +0000 Subject: [PATCH 07/88] Use spaces for easier debug --- session.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/session.py b/session.py index 96b6de026..bc25a9b2d 100644 --- a/session.py +++ b/session.py @@ -76,14 +76,14 @@ def getJson(session, url: str, headers: {}, params: {}, result = session.get(url, headers=sessionHeaders, params=sessionParams) return result.json() except requests.exceptions.RequestException as e: - print('ERROR: getJson failed\nurl: ' + str(url) + '\n' + - 'headers: ' + str(sessionHeaders) + '\n' + - 'params: ' + str(sessionParams) + '\n') + print('ERROR: getJson failed\nurl: ' + str(url) + ' ' + + 'headers: ' + str(sessionHeaders) + ' ' + + 'params: ' + str(sessionParams)) print(e) except ValueError as e: - print('ERROR: getJson failed\nurl: ' + str(url) + '\n' + - 'headers: ' + str(sessionHeaders) + '\n' + - 'params: ' + str(sessionParams) + '\n') + print('ERROR: getJson failed\nurl: ' + str(url) + ' ' + + 'headers: ' + str(sessionHeaders) + ' ' + + 'params: ' + str(sessionParams) + ' ') print(e) except SocketError as e: if e.errno == errno.ECONNRESET: From a1f677e380000fbbb0f53f4311b61f6ef410964e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 13:06:26 +0000 Subject: [PATCH 08/88] Consistent message --- session.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/session.py b/session.py index bc25a9b2d..f740c4759 100644 --- a/session.py +++ b/session.py @@ -58,7 +58,7 @@ def getJson(session, url: str, headers: {}, params: {}, domain='testdomain') -> {}: if not isinstance(url, str): print('url: ' + str(url)) - print('ERROR: getJson url should be a string') + print('ERROR: getJson failed, url should be a string') return None sessionParams = {} sessionHeaders = {} @@ -71,7 +71,7 @@ def getJson(session, url: str, headers: {}, params: {}, sessionHeaders['User-Agent'] += \ '; +' + httpPrefix + '://' + domain + '/' if not session: - print('WARN: no session specified for getJson') + print('WARN: getJson failed, no session specified for getJson') try: result = session.get(url, headers=sessionHeaders, params=sessionParams) return result.json() @@ -87,7 +87,7 @@ def getJson(session, url: str, headers: {}, params: {}, print(e) except SocketError as e: if e.errno == errno.ECONNRESET: - print('WARN: connection was reset during getJson') + print('WARN: getJson failed, connection was reset during getJson') print(e) return None From 0392e69cac6f72f4d4eb59d002a8d2ad2c1008a9 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 15:09:41 +0000 Subject: [PATCH 09/88] Add debug for sending posts --- posts.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/posts.py b/posts.py index 705de387a..ca0c9930c 100644 --- a/posts.py +++ b/posts.py @@ -2414,7 +2414,15 @@ def sendToFollowers(session, baseDir: str, clientToServer = False # for each instance + sendingStartTime = datetime.datetime.utcnow() + print('Sending post to followers begins ' + + sendingStartTime.strftime("%Y-%m-%dT%H:%M:%SZ")) + sendingCtr = 0 for followerDomain, followerHandles in grouped.items(): + print('Sending post to followers progress ' + + str(int(sendingCtr * 100 / len(grouped.items()))) + '%') + sendingCtr += 1 + if debug: print('DEBUG: follower handles for ' + followerDomain) pprint(followerHandles) @@ -2510,6 +2518,10 @@ def sendToFollowers(session, baseDir: str, if debug: print('DEBUG: End of sendToFollowers') + sendingEndTime = datetime.datetime.utcnow() + sendingMins = int((sendingEndTime - sendingStartTime).total_seconds() / 60) + print('Sending post to followers ends ' + str(sendingMins) + ' mins') + def sendToFollowersThread(session, baseDir: str, nickname: str, From 347626fd8a9cbc0c06cc0eb2fab9e73a64752a5c Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 15:11:06 +0000 Subject: [PATCH 10/88] Script to monitor sending of posts --- scripts/sending | 2 ++ 1 file changed, 2 insertions(+) create mode 100755 scripts/sending diff --git a/scripts/sending b/scripts/sending new file mode 100755 index 000000000..795033429 --- /dev/null +++ b/scripts/sending @@ -0,0 +1,2 @@ +#!/bin/bash +journalctl -u epicyon -r | grep "Sending post to followers" \ No newline at end of file From bb31ce37cdcf87d702114e5e595b72022bf3ebb2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 15:29:12 +0000 Subject: [PATCH 11/88] is_alive replaces isAlive --- daemon.py | 8 ++++---- inbox.py | 2 +- newsdaemon.py | 2 +- schedule.py | 2 +- tests.py | 40 ++++++++++++++++++++-------------------- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/daemon.py b/daemon.py index 20dc14b85..7ef72831e 100644 --- a/daemon.py +++ b/daemon.py @@ -1012,7 +1012,7 @@ class PubServer(BaseHTTPRequestHandler): print('Waiting for previous outbox thread to end') waitCtr = 0 thName = accountOutboxThreadName - while self.server.outboxThread[thName].isAlive() and waitCtr < 8: + while self.server.outboxThread[thName].is_alive() and waitCtr < 8: time.sleep(1) waitCtr += 1 if waitCtr >= 8: @@ -12087,7 +12087,7 @@ class PubServer(BaseHTTPRequestHandler): if self.server.newPostThread.get(newPostThreadName): print('Waiting for previous new post thread to end') waitCtr = 0 - while (self.server.newPostThread[newPostThreadName].isAlive() and + while (self.server.newPostThread[newPostThreadName].is_alive() and waitCtr < 8): time.sleep(1) waitCtr += 1 @@ -13005,7 +13005,7 @@ def runPostsWatchdog(projectVersion: str, httpd) -> None: httpd.thrPostsQueue.start() while True: time.sleep(20) - if not httpd.thrPostsQueue.isAlive(): + if not httpd.thrPostsQueue.is_alive(): httpd.thrPostsQueue.kill() httpd.thrPostsQueue = postsQueueOriginal.clone(runPostsQueue) httpd.thrPostsQueue.start() @@ -13020,7 +13020,7 @@ def runSharesExpireWatchdog(projectVersion: str, httpd) -> None: httpd.thrSharesExpire.start() while True: time.sleep(20) - if not httpd.thrSharesExpire.isAlive(): + if not httpd.thrSharesExpire.is_alive(): httpd.thrSharesExpire.kill() httpd.thrSharesExpire = sharesExpireOriginal.clone(runSharesExpire) httpd.thrSharesExpire.start() diff --git a/inbox.py b/inbox.py index 9a2536837..192a34f37 100644 --- a/inbox.py +++ b/inbox.py @@ -2456,7 +2456,7 @@ def runInboxQueueWatchdog(projectVersion: str, httpd) -> None: httpd.thrInboxQueue.start() while True: time.sleep(20) - if not httpd.thrInboxQueue.isAlive() or httpd.restartInboxQueue: + if not httpd.thrInboxQueue.is_alive() or httpd.restartInboxQueue: httpd.restartInboxQueueInProgress = True httpd.thrInboxQueue.kill() httpd.thrInboxQueue = inboxQueueOriginal.clone(runInboxQueue) diff --git a/newsdaemon.py b/newsdaemon.py index 42a69994b..c89ae24ef 100644 --- a/newsdaemon.py +++ b/newsdaemon.py @@ -752,7 +752,7 @@ def runNewswireWatchdog(projectVersion: str, httpd) -> None: httpd.thrNewswireDaemon.start() while True: time.sleep(50) - if not httpd.thrNewswireDaemon.isAlive(): + if not httpd.thrNewswireDaemon.is_alive(): httpd.thrNewswireDaemon.kill() httpd.thrNewswireDaemon = \ newswireOriginal.clone(runNewswireDaemon) diff --git a/schedule.py b/schedule.py index c213c4ec5..29808ca23 100644 --- a/schedule.py +++ b/schedule.py @@ -158,7 +158,7 @@ def runPostScheduleWatchdog(projectVersion: str, httpd) -> None: httpd.thrPostSchedule.start() while True: time.sleep(20) - if not httpd.thrPostSchedule.isAlive(): + if not httpd.thrPostSchedule.is_alive(): httpd.thrPostSchedule.kill() httpd.thrPostSchedule = \ postScheduleOriginal.clone(runPostSchedule) diff --git a/tests.py b/tests.py index 4b41b1fc4..ca0d1bbc2 100644 --- a/tests.py +++ b/tests.py @@ -236,11 +236,11 @@ def testThreads(): args=('test',), daemon=True) thr.start() - assert thr.isAlive() is True + assert thr.is_alive() is True time.sleep(1) thr.kill() thr.join() - assert thr.isAlive() is False + assert thr.is_alive() is False def createServerAlice(path: str, domain: str, port: int, @@ -462,7 +462,7 @@ def testPostMessageBetweenServers(): global thrAlice if thrAlice: - while thrAlice.isAlive(): + while thrAlice.is_alive(): thrAlice.stop() time.sleep(1) thrAlice.kill() @@ -476,7 +476,7 @@ def testPostMessageBetweenServers(): global thrBob if thrBob: - while thrBob.isAlive(): + while thrBob.is_alive(): thrBob.stop() time.sleep(1) thrBob.kill() @@ -490,8 +490,8 @@ def testPostMessageBetweenServers(): thrAlice.start() thrBob.start() - assert thrAlice.isAlive() is True - assert thrBob.isAlive() is True + assert thrAlice.is_alive() is True + assert thrBob.is_alive() is True # wait for both servers to be running while not (testServerAliceRunning and testServerBobRunning): @@ -690,11 +690,11 @@ def testPostMessageBetweenServers(): # stop the servers thrAlice.kill() thrAlice.join() - assert thrAlice.isAlive() is False + assert thrAlice.is_alive() is False thrBob.kill() thrBob.join() - assert thrBob.isAlive() is False + assert thrBob.is_alive() is False os.chdir(baseDir) shutil.rmtree(aliceDir) @@ -733,7 +733,7 @@ def testFollowBetweenServers(): global thrAlice if thrAlice: - while thrAlice.isAlive(): + while thrAlice.is_alive(): thrAlice.stop() time.sleep(1) thrAlice.kill() @@ -747,7 +747,7 @@ def testFollowBetweenServers(): global thrBob if thrBob: - while thrBob.isAlive(): + while thrBob.is_alive(): thrBob.stop() time.sleep(1) thrBob.kill() @@ -761,8 +761,8 @@ def testFollowBetweenServers(): thrAlice.start() thrBob.start() - assert thrAlice.isAlive() is True - assert thrBob.isAlive() is True + assert thrAlice.is_alive() is True + assert thrBob.is_alive() is True # wait for all servers to be running ctr = 0 @@ -862,11 +862,11 @@ def testFollowBetweenServers(): # stop the servers thrAlice.kill() thrAlice.join() - assert thrAlice.isAlive() is False + assert thrAlice.is_alive() is False thrBob.kill() thrBob.join() - assert thrBob.isAlive() is False + assert thrBob.is_alive() is False # queue item removed time.sleep(4) @@ -1290,7 +1290,7 @@ def testClientToServer(): global thrAlice if thrAlice: - while thrAlice.isAlive(): + while thrAlice.is_alive(): thrAlice.stop() time.sleep(1) thrAlice.kill() @@ -1304,7 +1304,7 @@ def testClientToServer(): global thrBob if thrBob: - while thrBob.isAlive(): + while thrBob.is_alive(): thrBob.stop() time.sleep(1) thrBob.kill() @@ -1318,8 +1318,8 @@ def testClientToServer(): thrAlice.start() thrBob.start() - assert thrAlice.isAlive() is True - assert thrBob.isAlive() is True + assert thrAlice.is_alive() is True + assert thrBob.is_alive() is True # wait for both servers to be running ctr = 0 @@ -1614,11 +1614,11 @@ def testClientToServer(): # stop the servers thrAlice.kill() thrAlice.join() - assert thrAlice.isAlive() is False + assert thrAlice.is_alive() is False thrBob.kill() thrBob.join() - assert thrBob.isAlive() is False + assert thrBob.is_alive() is False os.chdir(baseDir) # shutil.rmtree(aliceDir) From ddaa94146f2b7a2e738238f344733190eca79dea Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 17:02:26 +0000 Subject: [PATCH 12/88] Tidying --- posts.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/posts.py b/posts.py index ca0c9930c..8acd53045 100644 --- a/posts.py +++ b/posts.py @@ -142,17 +142,21 @@ def cleanHtml(rawHtml: str) -> str: def getUserUrl(wfRequest: {}) -> str: - if wfRequest.get('links'): - for link in wfRequest['links']: - if link.get('type') and link.get('href'): - if link['type'] == 'application/activity+json': - if not ('/users/' in link['href'] or - '/accounts/' in link['href'] or - '/profile/' in link['href'] or - '/channel/' in link['href']): - print('Webfinger activity+json contains ' + - 'single user instance actor') - return link['href'] + if not wfRequest.get('links'): + return None + for link in wfRequest['links']: + if not (link.get('type') and link.get('href')): + continue + if link['type'] != 'application/activity+json': + continue + if not ('/users/' in link['href'] or + '/accounts/' in link['href'] or + '/profile/' in link['href'] or + '/channel/' in link['href']): + print('Webfinger activity+json ' + + 'contains single user instance actor ' + + str(link)) + return link['href'] return None From 22f7f57b745d8ad4c563835a0d1f21e627d356e3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 17:08:35 +0000 Subject: [PATCH 13/88] More debug --- posts.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/posts.py b/posts.py index 8acd53045..96f8ded49 100644 --- a/posts.py +++ b/posts.py @@ -142,7 +142,12 @@ def cleanHtml(rawHtml: str) -> str: def getUserUrl(wfRequest: {}) -> str: + """Gets the actor url from a webfinger request + """ + print('getUserUrl: ' + str(wfRequest)) if not wfRequest.get('links'): + print('getUserUrl webfinger activity+json contains no links ' + + str(wfRequest)) return None for link in wfRequest['links']: if not (link.get('type') and link.get('href')): @@ -153,7 +158,7 @@ def getUserUrl(wfRequest: {}) -> str: '/accounts/' in link['href'] or '/profile/' in link['href'] or '/channel/' in link['href']): - print('Webfinger activity+json ' + + print('getUserUrl webfinger activity+json ' + 'contains single user instance actor ' + str(link)) return link['href'] From 2736b7252b49b0c51178a59693e00eb54cce82a0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 17:29:37 +0000 Subject: [PATCH 14/88] Debug --- webfinger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/webfinger.py b/webfinger.py index e95c8c7e1..8b64e17c2 100644 --- a/webfinger.py +++ b/webfinger.py @@ -67,6 +67,7 @@ def webfingerHandle(session, handle: str, httpPrefix: str, wf = getWebfingerFromCache(nickname + '@' + wfDomain, cachedWebfingers) if wf: + print('Webfinger from cache: ' + str(wf)) return wf url = '{}://{}/.well-known/webfinger'.format(httpPrefix, domain) par = { From af919974d7d36fa0728cebf058e592ac67aca144 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 17:49:17 +0000 Subject: [PATCH 15/88] Trace parameter --- announce.py | 2 +- availability.py | 2 +- bookmarks.py | 4 ++-- delete.py | 2 +- follow.py | 5 +++-- like.py | 5 +++-- posts.py | 35 +++++++++++++++++++++-------------- roles.py | 3 ++- shares.py | 6 ++++-- skills.py | 2 +- socnet.py | 3 ++- webapp_post.py | 3 ++- webapp_profile.py | 2 +- 13 files changed, 44 insertions(+), 30 deletions(-) diff --git a/announce.py b/announce.py index 386a63866..45be9351b 100644 --- a/announce.py +++ b/announce.py @@ -369,7 +369,7 @@ def sendAnnounceViaServer(baseDir: str, session, personCache, projectVersion, httpPrefix, fromNickname, fromDomain, - postToBox) + postToBox, 73528) if not inboxUrl: if debug: diff --git a/availability.py b/availability.py index b7739e86e..1dc7b03cf 100644 --- a/availability.py +++ b/availability.py @@ -123,7 +123,7 @@ def sendAvailabilityViaServer(baseDir: str, session, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, nickname, - domain, postToBox) + domain, postToBox, 57262) if not inboxUrl: if debug: diff --git a/bookmarks.py b/bookmarks.py index c0ef808a1..75eeac47c 100644 --- a/bookmarks.py +++ b/bookmarks.py @@ -441,7 +441,7 @@ def sendBookmarkViaServer(baseDir: str, session, fromPersonId, sharedInbox, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, 72483) if not inboxUrl: if debug: @@ -518,7 +518,7 @@ def sendUndoBookmarkViaServer(baseDir: str, session, fromPersonId, sharedInbox, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, 72528) if not inboxUrl: if debug: diff --git a/delete.py b/delete.py index 8302da1ed..524004d8b 100644 --- a/delete.py +++ b/delete.py @@ -136,7 +136,7 @@ def sendDeleteViaServer(baseDir: str, session, fromPersonId, sharedInbox, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, 53036) if not inboxUrl: if debug: diff --git a/follow.py b/follow.py index 58c1dfb6d..441d02fdf 100644 --- a/follow.py +++ b/follow.py @@ -995,7 +995,7 @@ def sendFollowRequestViaServer(baseDir: str, session, fromPersonId, sharedInbox, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, 52025) if not inboxUrl: if debug: @@ -1086,7 +1086,8 @@ def sendUnfollowRequestViaServer(baseDir: str, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, + 76536) if not inboxUrl: if debug: diff --git a/like.py b/like.py index 6076c7299..7f59e6167 100644 --- a/like.py +++ b/like.py @@ -257,7 +257,7 @@ def sendLikeViaServer(baseDir: str, session, personCache, projectVersion, httpPrefix, fromNickname, fromDomain, - postToBox) + postToBox, 72873) if not inboxUrl: if debug: @@ -335,7 +335,8 @@ def sendUndoLikeViaServer(baseDir: str, session, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, + 72625) if not inboxUrl: if debug: diff --git a/posts.py b/posts.py index 96f8ded49..2f629d53d 100644 --- a/posts.py +++ b/posts.py @@ -141,13 +141,13 @@ def cleanHtml(rawHtml: str) -> str: return html.unescape(text) -def getUserUrl(wfRequest: {}) -> str: +def getUserUrl(wfRequest: {}, sourceId=0) -> str: """Gets the actor url from a webfinger request """ - print('getUserUrl: ' + str(wfRequest)) + print('getUserUrl: ' + str(sourceId) + ' ' + str(wfRequest)) if not wfRequest.get('links'): print('getUserUrl webfinger activity+json contains no links ' + - str(wfRequest)) + str(sourceId) + ' ' + str(wfRequest)) return None for link in wfRequest['links']: if not (link.get('type') and link.get('href')): @@ -160,7 +160,7 @@ def getUserUrl(wfRequest: {}) -> str: '/channel/' in link['href']): print('getUserUrl webfinger activity+json ' + 'contains single user instance actor ' + - str(link)) + str(sourceId) + ' ' + str(link)) return link['href'] return None @@ -207,13 +207,14 @@ def getPersonBox(baseDir: str, session, wfRequest: {}, personCache: {}, projectVersion: str, httpPrefix: str, nickname: str, domain: str, - boxName='inbox') -> (str, str, str, str, str, str, str, str): + boxName='inbox', + sourceId=0) -> (str, str, str, str, str, str, str, str): profileStr = 'https://www.w3.org/ns/activitystreams' asHeader = { 'Accept': 'application/activity+json; profile="' + profileStr + '"' } if not wfRequest.get('errors'): - personUrl = getUserUrl(wfRequest) + personUrl = getUserUrl(wfRequest, sourceId) else: if nickname == 'dev': # try single user instance @@ -1774,7 +1775,8 @@ def sendPost(projectVersion: str, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, postToBox) + nickname, domain, postToBox, + 72533) if not inboxUrl: return 3 @@ -1889,7 +1891,8 @@ def sendPostViaServer(projectVersion: str, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, + 82796) if not inboxUrl: if debug: print('DEBUG: No ' + postToBox + ' was found for ' + handle) @@ -2088,7 +2091,8 @@ def sendSignedJson(postJsonObject: {}, session, baseDir: str, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, postToBox) + nickname, domain, postToBox, + 30873) print("inboxUrl: " + str(inboxUrl)) print("toPersonId: " + str(toPersonId)) @@ -3396,7 +3400,8 @@ def getPublicPostsOfPerson(baseDir: str, nickname: str, domain: str, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, 'outbox') + nickname, domain, 'outbox', + 62524) maxMentions = 10 maxEmoji = 10 maxAttachments = 5 @@ -3437,7 +3442,8 @@ def getPublicPostDomains(session, baseDir: str, nickname: str, domain: str, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, 'outbox') + nickname, domain, 'outbox', + 92522) maxMentions = 99 maxEmoji = 99 maxAttachments = 5 @@ -3480,7 +3486,8 @@ def getPublicPostInfo(session, baseDir: str, nickname: str, domain: str, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, 'outbox') + nickname, domain, 'outbox', + 13863) maxMentions = 99 maxEmoji = 99 maxAttachments = 5 @@ -3995,7 +4002,7 @@ def sendBlockViaServer(baseDir: str, session, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, 72652) if not inboxUrl: if debug: @@ -4077,7 +4084,7 @@ def sendUndoBlockViaServer(baseDir: str, session, fromPersonId, sharedInbox, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, 53892) if not inboxUrl: if debug: diff --git a/roles.py b/roles.py index ecbf237b8..a03a34ba7 100644 --- a/roles.py +++ b/roles.py @@ -316,7 +316,8 @@ def sendRoleViaServer(baseDir: str, session, wfRequest, personCache, projectVersion, httpPrefix, delegatorNickname, - delegatorDomain, postToBox) + delegatorDomain, postToBox, + 765672) if not inboxUrl: if debug: diff --git a/shares.py b/shares.py index 1926395a4..cb0867cba 100644 --- a/shares.py +++ b/shares.py @@ -376,7 +376,8 @@ def sendShareViaServer(baseDir, session, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, + 83653) if not inboxUrl: if debug: @@ -474,7 +475,8 @@ def sendUndoShareViaServer(baseDir: str, session, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, fromNickname, - fromDomain, postToBox) + fromDomain, postToBox, + 12663) if not inboxUrl: if debug: diff --git a/skills.py b/skills.py index 2b4930ff2..2637acd78 100644 --- a/skills.py +++ b/skills.py @@ -152,7 +152,7 @@ def sendSkillViaServer(baseDir: str, session, nickname: str, password: str, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, nickname, domain, - postToBox) + postToBox, 86725) if not inboxUrl: if debug: diff --git a/socnet.py b/socnet.py index 31c59eb88..36b5c7cb4 100644 --- a/socnet.py +++ b/socnet.py @@ -65,7 +65,8 @@ def instancesGraph(baseDir: str, handles: str, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, 'outbox') + nickname, domain, 'outbox', + 27261) postDomains = \ getPostDomains(session, personUrl, 64, maxMentions, maxEmoji, maxAttachments, federationList, diff --git a/webapp_post.py b/webapp_post.py index 5ad029320..28891dca5 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -1179,7 +1179,8 @@ def individualPostAsHtml(allowDownloads: bool, avatarUrl2, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, - nickname, domain, 'outbox') + nickname, domain, 'outbox', + 72367) logPostTiming(enableTimingLog, postStartTime, '6') if avatarUrl2: diff --git a/webapp_profile.py b/webapp_profile.py index c18c87945..f2f2a120d 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -1457,7 +1457,7 @@ def individualFollowAsHtml(translate: {}, avatarUrl2, displayName) = getPersonBox(baseDir, session, wfRequest, personCache, projectVersion, httpPrefix, nickname, - domain, 'outbox') + domain, 'outbox', 43036) if avatarUrl2: avatarUrl = avatarUrl2 if displayName: From 8c7071b6e3731484a43d07f67d0b7da95bb4e1d5 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 18:12:33 +0000 Subject: [PATCH 16/88] Single webfinger --- inbox.py | 10 +++++++++- webapp_profile.py | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/inbox.py b/inbox.py index 192a34f37..424d47665 100644 --- a/inbox.py +++ b/inbox.py @@ -173,9 +173,17 @@ def inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, avatarUrl = None if boxname != 'tlevents' and boxname != 'outbox': boxname = 'inbox' + + wfRequest = {} + requestHandle = nickname + '@' + domain + if cachedWebfingers.get(requestHandle): + wfRequest = cachedWebfingers[requestHandle] + elif cachedWebfingers.get(requestHandle + ':' + str(port)): + wfRequest = cachedWebfingers[requestHandle + ':' + str(port)] + individualPostAsHtml(True, recentPostsCache, maxRecentPosts, translate, pageNumber, - baseDir, session, cachedWebfingers, personCache, + baseDir, session, wfRequest, personCache, nickname, domain, port, postJsonObject, avatarUrl, True, allowDeletion, httpPrefix, __version__, boxname, None, diff --git a/webapp_profile.py b/webapp_profile.py index f2f2a120d..9df98ea6a 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -259,10 +259,18 @@ def htmlProfileAfterSearch(cssCache: {}, continue if not item.get('object'): continue + + wfRequest = {} + requestHandle = nickname + '@' + domain + if cachedWebfingers.get(requestHandle): + wfRequest = cachedWebfingers[requestHandle] + elif cachedWebfingers.get(requestHandle + ':' + str(port)): + wfRequest = cachedWebfingers[requestHandle + ':' + str(port)] + profileStr += \ individualPostAsHtml(True, recentPostsCache, maxRecentPosts, translate, None, baseDir, - session, cachedWebfingers, personCache, + session, wfRequest, personCache, nickname, domain, port, item, avatarUrl, False, False, httpPrefix, projectVersion, 'inbox', From 7ee21c5c30eb6049306aca38ca784d59d62e382f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 19:59:19 +0000 Subject: [PATCH 17/88] Debug for sending to followers --- posts.py | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/posts.py b/posts.py index 2f629d53d..6f22d6292 100644 --- a/posts.py +++ b/posts.py @@ -2433,26 +2433,29 @@ def sendToFollowers(session, baseDir: str, sendingCtr = 0 for followerDomain, followerHandles in grouped.items(): print('Sending post to followers progress ' + - str(int(sendingCtr * 100 / len(grouped.items()))) + '%') + str(int(sendingCtr * 100 / len(grouped.items()))) + '% ' + + followerDomain) sendingCtr += 1 if debug: - print('DEBUG: follower handles for ' + followerDomain) pprint(followerHandles) # check that the follower's domain is active followerDomainUrl = httpPrefix + '://' + followerDomain if not siteIsActive(followerDomainUrl): - print('Domain is inactive: ' + followerDomainUrl) + print('Sending post to followers domain is inactive: ' + + followerDomainUrl) continue - print('Domain is active: ' + followerDomainUrl) + print('Sending post to followers domain is active: ' + + followerDomainUrl) withSharedInbox = hasSharedInbox(session, httpPrefix, followerDomain) if debug: if withSharedInbox: print(followerDomain + ' has shared inbox') if not withSharedInbox: - print(followerDomain + ' does not have a shared inbox') + print('Sending post to followers, ' + followerDomain + + ' does not have a shared inbox') toPort = port index = 0 @@ -2486,13 +2489,13 @@ def sendToFollowers(session, baseDir: str, if toNickname != 'inbox' and postJsonObject.get('type'): if sendingProfileUpdate(postJsonObject): - print('Sending profile update to ' + + print('Sending post to followers ' + 'shared inbox of ' + toDomain) toNickname = 'inbox' - if debug: - print('DEBUG: Sending from ' + nickname + '@' + domain + - ' to ' + toNickname + '@' + toDomain) + print('Sending post to followers from ' + + nickname + '@' + domain + + ' to ' + toNickname + '@' + toDomain) sendSignedJson(postJsonObject, session, baseDir, nickname, fromDomain, port, @@ -2504,19 +2507,17 @@ def sendToFollowers(session, baseDir: str, else: # send to individual followers without using a shared inbox for handle in followerHandles: - if debug: - print('DEBUG: Sending to ' + handle) + print('Sending post to followers ' + handle) toNickname = handle.split('@')[0] - if debug: - if postJsonObject['type'] != 'Update': - print('DEBUG: Sending from ' + - nickname + '@' + domain + ' to ' + - toNickname + '@' + toDomain) - else: - print('DEBUG: Sending profile update from ' + - nickname + '@' + domain + ' to ' + - toNickname + '@' + toDomain) + if postJsonObject['type'] != 'Update': + print('Sending post to followers from ' + + nickname + '@' + domain + ' to ' + + toNickname + '@' + toDomain) + else: + print('Sending post to followers profile update from ' + + nickname + '@' + domain + ' to ' + + toNickname + '@' + toDomain) sendSignedJson(postJsonObject, session, baseDir, nickname, fromDomain, port, From 20e92a4220c10deb1c63a995fa3cc78d08d17c62 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 20:57:18 +0000 Subject: [PATCH 18/88] Try without cc --- daemon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/daemon.py b/daemon.py index 7ef72831e..e91588640 100644 --- a/daemon.py +++ b/daemon.py @@ -4549,7 +4549,6 @@ class PubServer(BaseHTTPRequestHandler): 'type': 'Update', 'actor': actorJson['id'], 'to': [pubStr], - 'cc': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) From 5ba7bed9a1754a50deb92b6b2091d0bc8cc85137 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 21:02:32 +0000 Subject: [PATCH 19/88] Swap to and cc --- daemon.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index e91588640..15191310e 100644 --- a/daemon.py +++ b/daemon.py @@ -4548,7 +4548,8 @@ class PubServer(BaseHTTPRequestHandler): 'id': actorJson['id'] + '#updates/' + pubNumber, 'type': 'Update', 'actor': actorJson['id'], - 'to': [pubStr], + 'cc': [pubStr], + 'to': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) From f7fc448d9b710f849f239347bf8683b833bffa05 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 21:31:08 +0000 Subject: [PATCH 20/88] Set some context --- daemon.py | 16 ++++++++++++++++ person.py | 7 ++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index 15191310e..66f1d1d67 100644 --- a/daemon.py +++ b/daemon.py @@ -3772,6 +3772,22 @@ class PubServer(BaseHTTPRequestHandler): # which isn't implemented in Epicyon actorJson['discoverable'] = False actorChanged = True + if not actorJson['@context'].get('orgSchema'): + actorJson['@context']['orgSchema'] = 'toot:orgSchema' + actorChanged = True + if not actorJson['@context'].get('skills'): + actorJson['@context']['skills'] = 'toot:skills' + actorChanged = True + if not actorJson['@context'].get('roles'): + actorJson['@context']['roles'] = 'toot:roles' + actorChanged = True + if not actorJson['@context'].get('availability'): + actorJson['@context']['availaibility'] = \ + 'toot:availability' + actorChanged = True + if actorJson.get('capabilityAcquisitionEndpoint'): + del actorJson['capabilityAcquisitionEndpoint'] + actorChanged = True # update the avatar/image url file extension uploads = profileMediaTypesUploaded.items() for mType, lastPart in uploads: diff --git a/person.py b/person.py index 9fcf099d2..6886421d2 100644 --- a/person.py +++ b/person.py @@ -191,7 +191,12 @@ def getDefaultPersonContext() -> str: 'fingerprintKey': {'@id': 'toot:fingerprintKey', '@type': '@id'}, 'messageFranking': 'toot:messageFranking', 'publicKeyBase64': 'toot:publicKeyBase64', - 'discoverable': 'toot:discoverable' + 'discoverable': 'toot:discoverable', + 'orgSchema': 'toot:orgSchema', + 'shares': 'toot:shares', + 'skills': 'toot:skills', + 'roles': 'toot:roles', + 'availability': 'toot:availability' } From f56a96a0d39f0ec8f9292e8fc354d5310e63eee6 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 21:35:17 +0000 Subject: [PATCH 21/88] Context list --- daemon.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/daemon.py b/daemon.py index 66f1d1d67..82780f62c 100644 --- a/daemon.py +++ b/daemon.py @@ -3772,17 +3772,17 @@ class PubServer(BaseHTTPRequestHandler): # which isn't implemented in Epicyon actorJson['discoverable'] = False actorChanged = True - if not actorJson['@context'].get('orgSchema'): - actorJson['@context']['orgSchema'] = 'toot:orgSchema' + if not actorJson['@context'][2].get('orgSchema'): + actorJson['@context'][2]['orgSchema'] = 'toot:orgSchema' actorChanged = True - if not actorJson['@context'].get('skills'): - actorJson['@context']['skills'] = 'toot:skills' + if not actorJson['@context'][2].get('skills'): + actorJson['@context'][2]['skills'] = 'toot:skills' actorChanged = True - if not actorJson['@context'].get('roles'): - actorJson['@context']['roles'] = 'toot:roles' + if not actorJson['@context'][2].get('roles'): + actorJson['@context'][2]['roles'] = 'toot:roles' actorChanged = True - if not actorJson['@context'].get('availability'): - actorJson['@context']['availaibility'] = \ + if not actorJson['@context'][2].get('availability'): + actorJson['@context'][2]['availaibility'] = \ 'toot:availability' actorChanged = True if actorJson.get('capabilityAcquisitionEndpoint'): From 61a9c5d6056da353266a471722a7a85aef72c2a4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 21:41:11 +0000 Subject: [PATCH 22/88] Extra context --- daemon.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/daemon.py b/daemon.py index 82780f62c..356972280 100644 --- a/daemon.py +++ b/daemon.py @@ -3778,12 +3778,18 @@ class PubServer(BaseHTTPRequestHandler): if not actorJson['@context'][2].get('skills'): actorJson['@context'][2]['skills'] = 'toot:skills' actorChanged = True + if not actorJson['@context'][2].get('shares'): + actorJson['@context'][2]['shares'] = 'toot:shares' + actorChanged = True if not actorJson['@context'][2].get('roles'): actorJson['@context'][2]['roles'] = 'toot:roles' actorChanged = True if not actorJson['@context'][2].get('availability'): actorJson['@context'][2]['availaibility'] = \ 'toot:availability' + if not actorJson['@context'][2].get('nomadicLocations'): + actorJson['@context'][2]['nomadicLocations'] = \ + 'toot:nomadicLocations' actorChanged = True if actorJson.get('capabilityAcquisitionEndpoint'): del actorJson['capabilityAcquisitionEndpoint'] From e438d1bd8f45469d5d4a1999184e4a967baea89c Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 21:43:08 +0000 Subject: [PATCH 23/88] Extra context --- person.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/person.py b/person.py index 6886421d2..406700b29 100644 --- a/person.py +++ b/person.py @@ -196,7 +196,8 @@ def getDefaultPersonContext() -> str: 'shares': 'toot:shares', 'skills': 'toot:skills', 'roles': 'toot:roles', - 'availability': 'toot:availability' + 'availability': 'toot:availability', + 'nomadicLocations': 'toot:nomadicLocations' } From 8150fc9c11c94ffa9893bfb0fa6968a4af477053 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 21:44:21 +0000 Subject: [PATCH 24/88] Sequence --- daemon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index 356972280..5b738e258 100644 --- a/daemon.py +++ b/daemon.py @@ -4570,8 +4570,8 @@ class PubServer(BaseHTTPRequestHandler): 'id': actorJson['id'] + '#updates/' + pubNumber, 'type': 'Update', 'actor': actorJson['id'], - 'cc': [pubStr], - 'to': [actorJson['id'] + '/followers'], + 'to': [pubStr], + 'cc': [actorJson['id'] + '/followers'], 'object': actorJson } print('Sending actor update: ' + str(updateActorJson)) From 5acc6fe3b2962d273ae100aac523b4afd5f8c494 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 23:10:55 +0000 Subject: [PATCH 25/88] Alternative path for avatar images --- daemon.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index 5b738e258..85862a857 100644 --- a/daemon.py +++ b/daemon.py @@ -3802,9 +3802,11 @@ class PubServer(BaseHTTPRequestHandler): lastPartOfUrl = \ actorJson['icon']['url'].split('/')[-1] srchStr = '/' + lastPartOfUrl + actorUrl = actorJson['icon']['url'] + actorUrl = actorUrl.replace(srchStr, repStr) actorJson['icon']['url'] = \ - actorJson['icon']['url'].replace(srchStr, - repStr) + actorUrl.replace('/users/', + '/accounts/avatars/') if '.' in actorJson['icon']['url']: imgExt = \ actorJson['icon']['url'].split('.')[-1] @@ -9359,6 +9361,16 @@ class PubServer(BaseHTTPRequestHandler): '_nodeinfo(callingDomain)', '_mastoApi(callingDomain)') + # alternative way of referencing avatar images + # /accounts/avatars/nickname/avatar[number].png + # instead of /users/nickname/avatar[number].png + if self.path.startswith('/accounts/avatars/'): + nickname = self.path.split('/accounts/avatars/')[1] + if '/' in nickname: + avatarFilename = nickname.split('/')[1] + nickname = nickname.split('/')[0] + self.path = '/users/' + nickname + '/' + avatarFilename + if self.path == '/logout': if not self.server.newsInstance: msg = \ From 1ec334a6d949d80a99fa1c1e98f7ed03264a9c51 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 23:23:05 +0000 Subject: [PATCH 26/88] Debug --- daemon.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/daemon.py b/daemon.py index 85862a857..75dcaa49a 100644 --- a/daemon.py +++ b/daemon.py @@ -3799,11 +3799,11 @@ class PubServer(BaseHTTPRequestHandler): for mType, lastPart in uploads: repStr = '/' + lastPart if mType == 'avatar': - lastPartOfUrl = \ - actorJson['icon']['url'].split('/')[-1] - srchStr = '/' + lastPartOfUrl actorUrl = actorJson['icon']['url'] + lastPartOfUrl = actorUrl.split('/')[-1] + srchStr = '/' + lastPartOfUrl actorUrl = actorUrl.replace(srchStr, repStr) + print('actorUrl: ' + actorUrl) actorJson['icon']['url'] = \ actorUrl.replace('/users/', '/accounts/avatars/') From 77ea08b7fcbadabbea66aee829cc5afc9ac16ce1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 23:27:26 +0000 Subject: [PATCH 27/88] Tidying --- daemon.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/daemon.py b/daemon.py index 75dcaa49a..eea17a09b 100644 --- a/daemon.py +++ b/daemon.py @@ -3803,13 +3803,12 @@ class PubServer(BaseHTTPRequestHandler): lastPartOfUrl = actorUrl.split('/')[-1] srchStr = '/' + lastPartOfUrl actorUrl = actorUrl.replace(srchStr, repStr) + actorUrl = actorUrl.replace('/users/', + '/accounts/avatars/') + actorJson['icon']['url'] = actorUrl print('actorUrl: ' + actorUrl) - actorJson['icon']['url'] = \ - actorUrl.replace('/users/', - '/accounts/avatars/') - if '.' in actorJson['icon']['url']: - imgExt = \ - actorJson['icon']['url'].split('.')[-1] + if '.' in actorUrl: + imgExt = actorUrl.split('.')[-1] if imgExt == 'jpg': imgExt = 'jpeg' actorJson['icon']['mediaType'] = \ From 30d95182d3a3897e302c7038ec2d7cdecb3b5c56 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 23:34:52 +0000 Subject: [PATCH 28/88] Change avatar path --- person.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/person.py b/person.py index 406700b29..f4115a810 100644 --- a/person.py +++ b/person.py @@ -154,7 +154,7 @@ def randomizeActorImages(personJson: {}) -> None: # secure names randStr = str(randint(10000000000000, 99999999999999)) # nosec personJson['icon']['url'] = \ - personId + '/avatar' + randStr + '.' + existingExtension + '/accounts/avatars/avatar' + randStr + '.' + existingExtension lastPartOfFilename = personJson['image']['url'].split('/')[-1] existingExtension = lastPartOfFilename.split('.')[1] randStr = str(randint(10000000000000, 99999999999999)) # nosec From 9dd5ac532f3785a5231cfef66c9548d87aee46f9 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 23:38:15 +0000 Subject: [PATCH 29/88] Change avatar path --- person.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/person.py b/person.py index f4115a810..f470b4448 100644 --- a/person.py +++ b/person.py @@ -148,13 +148,15 @@ def randomizeActorImages(personJson: {}) -> None: This causes other instances to update their cached avatar image """ personId = personJson['id'] + nickname = personId.split('/users/')[1] lastPartOfFilename = personJson['icon']['url'].split('/')[-1] existingExtension = lastPartOfFilename.split('.')[1] # NOTE: these files don't need to have cryptographically # secure names randStr = str(randint(10000000000000, 99999999999999)) # nosec personJson['icon']['url'] = \ - '/accounts/avatars/avatar' + randStr + '.' + existingExtension + '/accounts/avatars/' + nickname + \ + '/avatar' + randStr + '.' + existingExtension lastPartOfFilename = personJson['image']['url'].split('/')[-1] existingExtension = lastPartOfFilename.split('.')[1] randStr = str(randint(10000000000000, 99999999999999)) # nosec From 93da5f9b72a09253e0383cb35e8c5446ee148cf4 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 18 Dec 2020 23:44:44 +0000 Subject: [PATCH 30/88] Revert to previous avatar path --- daemon.py | 12 ------------ person.py | 4 +--- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/daemon.py b/daemon.py index eea17a09b..529793325 100644 --- a/daemon.py +++ b/daemon.py @@ -3803,8 +3803,6 @@ class PubServer(BaseHTTPRequestHandler): lastPartOfUrl = actorUrl.split('/')[-1] srchStr = '/' + lastPartOfUrl actorUrl = actorUrl.replace(srchStr, repStr) - actorUrl = actorUrl.replace('/users/', - '/accounts/avatars/') actorJson['icon']['url'] = actorUrl print('actorUrl: ' + actorUrl) if '.' in actorUrl: @@ -9360,16 +9358,6 @@ class PubServer(BaseHTTPRequestHandler): '_nodeinfo(callingDomain)', '_mastoApi(callingDomain)') - # alternative way of referencing avatar images - # /accounts/avatars/nickname/avatar[number].png - # instead of /users/nickname/avatar[number].png - if self.path.startswith('/accounts/avatars/'): - nickname = self.path.split('/accounts/avatars/')[1] - if '/' in nickname: - avatarFilename = nickname.split('/')[1] - nickname = nickname.split('/')[0] - self.path = '/users/' + nickname + '/' + avatarFilename - if self.path == '/logout': if not self.server.newsInstance: msg = \ diff --git a/person.py b/person.py index f470b4448..406700b29 100644 --- a/person.py +++ b/person.py @@ -148,15 +148,13 @@ def randomizeActorImages(personJson: {}) -> None: This causes other instances to update their cached avatar image """ personId = personJson['id'] - nickname = personId.split('/users/')[1] lastPartOfFilename = personJson['icon']['url'].split('/')[-1] existingExtension = lastPartOfFilename.split('.')[1] # NOTE: these files don't need to have cryptographically # secure names randStr = str(randint(10000000000000, 99999999999999)) # nosec personJson['icon']['url'] = \ - '/accounts/avatars/' + nickname + \ - '/avatar' + randStr + '.' + existingExtension + personId + '/avatar' + randStr + '.' + existingExtension lastPartOfFilename = personJson['image']['url'].split('/')[-1] existingExtension = lastPartOfFilename.split('.')[1] randStr = str(randint(10000000000000, 99999999999999)) # nosec From 8f1ded15a366b73d0c958e06069bd2ff51888154 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 10:10:47 +0000 Subject: [PATCH 31/88] Apply word filter to skill names --- daemon.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index 529793325..232f64edb 100644 --- a/daemon.py +++ b/daemon.py @@ -3773,7 +3773,8 @@ class PubServer(BaseHTTPRequestHandler): actorJson['discoverable'] = False actorChanged = True if not actorJson['@context'][2].get('orgSchema'): - actorJson['@context'][2]['orgSchema'] = 'toot:orgSchema' + actorJson['@context'][2]['orgSchema'] = \ + 'toot:orgSchema' actorChanged = True if not actorJson['@context'][2].get('skills'): actorJson['@context'][2]['skills'] = 'toot:skills' @@ -3835,6 +3836,9 @@ class PubServer(BaseHTTPRequestHandler): if not skillName: skillCtr += 1 continue + if isFiltered(baseDir, nickname, domain, skillName): + skillCtr += 1 + continue skillValue = \ fields.get('skillValue' + str(skillCtr)) if not skillValue: From 84a00f3946859edc907ecc775afca463d280bfcb Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 10:15:56 +0000 Subject: [PATCH 32/88] Add skill names to the skills category --- daemon.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/daemon.py b/daemon.py index 232f64edb..ac627d49a 100644 --- a/daemon.py +++ b/daemon.py @@ -3851,6 +3851,9 @@ class PubServer(BaseHTTPRequestHandler): int(skillValue): actorChanged = True newSkills[skillName] = int(skillValue) + skillsStr = self.server.translate['Skills'] + setHashtagCategory(baseDir, skillName, + skillsStr.lower()) skillCtr += 1 if len(actorJson['skills'].items()) != \ len(newSkills.items()): From 0d9a12ac221a70f6768d576d3d7c907defb3ac51 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 10:32:48 +0000 Subject: [PATCH 33/88] Filter the display of skill names --- webapp_profile.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webapp_profile.py b/webapp_profile.py index 9df98ea6a..5cf2ec3cb 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -34,6 +34,7 @@ from pgp import getPGPfingerprint from pgp import getPGPpubKey from tox import getToxAddress from jami import getJamiAddress +from filters import isFiltered from webapp_frontscreen import htmlFrontScreen from webapp_utils import scheduledPostsExist from webapp_utils import getPersonAvatarUrl @@ -990,6 +991,8 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, skillCtr = 1 if skills: for skillDesc, skillValue in skills.items(): + if isFiltered(baseDir, nickname, domain, skillDesc): + continue skillsStr += \ '


\n' + tlStr += \ ' \n' + tlStr += \ ' \n' + tlStr += \ ' \n' + + tlStr += \ + ' \n' + tlStr += \ + ' \n' + tlStr += '\n\n' logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '6') From c447f90ec9239e7c83fafb0c0fe63b9694262ecf Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 11:29:55 +0000 Subject: [PATCH 39/88] Add and remove global word filters from moderator screen --- daemon.py | 10 ++++++++++ filters.py | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/daemon.py b/daemon.py index ac627d49a..0b18109b7 100644 --- a/daemon.py +++ b/daemon.py @@ -239,6 +239,8 @@ from newswire import loadHashtagCategories from newsdaemon import runNewswireWatchdog from newsdaemon import runNewswireDaemon from filters import isFiltered +from filters import addGlobalFilter +from filters import removeGlobalFilter import os @@ -1506,6 +1508,10 @@ class PubServer(BaseHTTPRequestHandler): moderationButton = 'block' elif moderationStr.startswith('submitUnblock'): moderationButton = 'unblock' + elif moderationStr.startswith('submitFilter'): + moderationButton = 'filter' + elif moderationStr.startswith('submitUnfilter'): + moderationButton = 'unfilter' elif moderationStr.startswith('submitSuspend'): moderationButton = 'suspend' elif moderationStr.startswith('submitUnsuspend'): @@ -1526,6 +1532,10 @@ class PubServer(BaseHTTPRequestHandler): suspendAccount(baseDir, nickname, domain) if moderationButton == 'unsuspend': unsuspendAccount(baseDir, nickname) + if moderationButton == 'filter': + addGlobalFilter(baseDir, moderationText) + if moderationButton == 'unfilter': + removeGlobalFilter(baseDir, moderationText) if moderationButton == 'block': fullBlockDomain = None if moderationText.startswith('http') or \ diff --git a/filters.py b/filters.py index 388857111..42db49591 100644 --- a/filters.py +++ b/filters.py @@ -23,6 +23,20 @@ def addFilter(baseDir: str, nickname: str, domain: str, words: str) -> bool: return True +def addGlobalFilter(baseDir: str, words: str) -> bool: + """Adds a global filter for particular words within + the content of a incoming posts + """ + filtersFilename = baseDir + '/accounts/filters.txt' + if os.path.isfile(filtersFilename): + if words in open(filtersFilename).read(): + return False + filtersFile = open(filtersFilename, "a+") + filtersFile.write(words + '\n') + filtersFile.close() + return True + + def removeFilter(baseDir: str, nickname: str, domain: str, words: str) -> bool: """Removes a word filter @@ -43,6 +57,24 @@ def removeFilter(baseDir: str, nickname: str, domain: str, return False +def removeGlobalFilter(baseDir: str, words: str) -> bool: + """Removes a global word filter + """ + filtersFilename = baseDir + '/accounts/filters.txt' + if os.path.isfile(filtersFilename): + if words in open(filtersFilename).read(): + with open(filtersFilename, 'r') as fp: + with open(filtersFilename + '.new', 'w+') as fpnew: + for line in fp: + line = line.replace('\n', '') + if line != words: + fpnew.write(line + '\n') + if os.path.isfile(filtersFilename + '.new'): + os.rename(filtersFilename + '.new', filtersFilename) + return True + return False + + def isTwitterPost(content: str) -> bool: """Returns true if the given post content is a retweet or twitter crosspost """ @@ -66,9 +98,9 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: if isTwitterPost(content): return True - instanceFiltersFilename = baseDir + '/accounts/filters.txt' - if os.path.isfile(instanceFiltersFilename): - if content + '\n' in open(instanceFiltersFilename).read(): + globalFiltersFilename = baseDir + '/accounts/filters.txt' + if os.path.isfile(globalFiltersFilename): + if content + '\n' in open(globalFiltersFilename).read(): return True accountFiltersFilename = baseDir + '/accounts/' + \ From cc2b9735fc9b43458ff670df239f3fe0c963d964 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 11:33:38 +0000 Subject: [PATCH 40/88] Show filtered words on moderator info screen --- webapp_moderation.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/webapp_moderation.py b/webapp_moderation.py index 63889536b..46c5ba634 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -185,6 +185,22 @@ def htmlModerationInfo(cssCache: {}, translate: {}, blockedStr + '' infoForm += '' infoShown = True + + filtersFilename = baseDir + '/accounts/filters.txt' + if os.path.isfile(filtersFilename): + with open(filtersFilename, "r") as f: + filteredStr = f.read() + infoForm += '

' + infoForm += \ + '
' + \ + translate['Filtered words'] + '' + infoForm += \ + ' ' + infoForm += '
' + infoShown = True + if not infoShown: infoForm += \ '

' + \ From 97a5b774d4ccc8bcd5f3bde3dd52532bbf4975d7 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 11:41:40 +0000 Subject: [PATCH 41/88] Allow filtering without an account --- filters.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/filters.py b/filters.py index 42db49591..fda11fafc 100644 --- a/filters.py +++ b/filters.py @@ -91,6 +91,14 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: You can add individual words or use word1+word2 to indicate that two words must be present although not necessarily adjacent """ + globalFiltersFilename = baseDir + '/accounts/filters.txt' + if os.path.isfile(globalFiltersFilename): + if content + '\n' in open(globalFiltersFilename).read(): + return True + + if not nickname or not domain: + return False + # optionally remove retweets removeTwitter = baseDir + '/accounts/' + \ nickname + '@' + domain + '/.removeTwitter' @@ -98,11 +106,6 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: if isTwitterPost(content): return True - globalFiltersFilename = baseDir + '/accounts/filters.txt' - if os.path.isfile(globalFiltersFilename): - if content + '\n' in open(globalFiltersFilename).read(): - return True - accountFiltersFilename = baseDir + '/accounts/' + \ nickname + '@' + domain + '/filters.txt' if os.path.isfile(accountFiltersFilename): From a7d5c5022278461d6bb0f6b6b2f0c5cf85bc1448 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 11:43:20 +0000 Subject: [PATCH 42/88] Use global filter for newswire --- newswire.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newswire.py b/newswire.py index 9b60041b3..88c71fb28 100644 --- a/newswire.py +++ b/newswire.py @@ -110,7 +110,7 @@ def addNewswireDictEntry(baseDir: str, domain: str, allText = title + ' ' + description # check that none of the text is filtered against - if isFiltered(baseDir, 'news', domain, allText): + if isFiltered(baseDir, None, None, allText): return if tags is None: From 2e1efdbee873a4683fb719734fa4852c65db00cd Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 12:47:43 +0000 Subject: [PATCH 43/88] Filter user bio --- daemon.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/daemon.py b/daemon.py index 0b18109b7..28d8c93df 100644 --- a/daemon.py +++ b/daemon.py @@ -4174,18 +4174,20 @@ class PubServer(BaseHTTPRequestHandler): if fields.get('bio'): if fields['bio'] != actorJson['summary']: bioStr = removeHtml(fields['bio']) - actorTags = {} - actorJson['summary'] = \ - addHtmlTags(baseDir, - httpPrefix, - nickname, - domainFull, - bioStr, [], actorTags) - if actorTags: - actorJson['tag'] = [] - for tagName, tag in actorTags.items(): - actorJson['tag'].append(tag) - actorChanged = True + if not isFiltered(baseDir, + nickname, domain, bioStr): + actorTags = {} + actorJson['summary'] = \ + addHtmlTags(baseDir, + httpPrefix, + nickname, + domainFull, + bioStr, [], actorTags) + if actorTags: + actorJson['tag'] = [] + for tagName, tag in actorTags.items(): + actorJson['tag'].append(tag) + actorChanged = True else: if actorJson['summary']: actorJson['summary'] = '' From 86c1a678dccce5e64cceef02655015fdc436bcbe Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 12:51:13 +0000 Subject: [PATCH 44/88] Filter bio on profile screen --- webapp_profile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp_profile.py b/webapp_profile.py index 5cf2ec3cb..a60256b15 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -885,6 +885,8 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, if actorJson.get('summary'): bioStr = \ actorJson['summary'].replace('

', '').replace('

', '') + if isFiltered(baseDir, nickname, domain, bioStr): + bioStr = '' if actorJson.get('manuallyApprovesFollowers'): if actorJson['manuallyApprovesFollowers']: manuallyApprovesFollowers = 'checked' From 536a69e8ef2343403bc4a3114180375f6b9ed979 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 12:55:40 +0000 Subject: [PATCH 45/88] Filter display name --- daemon.py | 8 ++++++-- webapp_profile.py | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/daemon.py b/daemon.py index 28d8c93df..9a8ac40bb 100644 --- a/daemon.py +++ b/daemon.py @@ -3885,9 +3885,13 @@ class PubServer(BaseHTTPRequestHandler): # change displayed name if fields.get('displayNickname'): if fields['displayNickname'] != actorJson['name']: - actorJson['name'] = \ + displayName = \ removeHtml(fields['displayNickname']) - actorChanged = True + if not isFiltered(baseDir, + nickname, domain, + displayName): + actorJson['name'] = displayName + actorChanged = True # change media instance status if fields.get('mediaInstance'): diff --git a/webapp_profile.py b/webapp_profile.py index a60256b15..625c75c0a 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -881,7 +881,8 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str, PGPpubKey = getPGPpubKey(actorJson) PGPfingerprint = getPGPfingerprint(actorJson) if actorJson.get('name'): - displayNickname = actorJson['name'] + if not isFiltered(baseDir, nickname, domain, actorJson['name']): + displayNickname = actorJson['name'] if actorJson.get('summary'): bioStr = \ actorJson['summary'].replace('

', '').replace('

', '') From dfffd4e296e5b36b96ce096352db912efb409f80 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 12:56:32 +0000 Subject: [PATCH 46/88] Default display name if filtered --- daemon.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index 9a8ac40bb..35d8232f5 100644 --- a/daemon.py +++ b/daemon.py @@ -3891,7 +3891,9 @@ class PubServer(BaseHTTPRequestHandler): nickname, domain, displayName): actorJson['name'] = displayName - actorChanged = True + else: + actorJson['name'] = nickname + actorChanged = True # change media instance status if fields.get('mediaInstance'): From c7051f191fe93e0627e623c0ae7d906f3401f48b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 13:00:35 +0000 Subject: [PATCH 47/88] Improve global filtering --- filters.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/filters.py b/filters.py index fda11fafc..4ae1fcede 100644 --- a/filters.py +++ b/filters.py @@ -93,8 +93,12 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: """ globalFiltersFilename = baseDir + '/accounts/filters.txt' if os.path.isfile(globalFiltersFilename): - if content + '\n' in open(globalFiltersFilename).read(): - return True + wordsFile = open(globalFiltersFilename, 'r') + if wordsFile: + wordsList = wordsFile.read().split('\n') + for word in wordsList: + if word in content: + return True if not nickname or not domain: return False From 50ae2cec61836d963aa05abef705364fa39ac23c Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 13:07:42 +0000 Subject: [PATCH 48/88] Minimum word length --- filters.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/filters.py b/filters.py index 4ae1fcede..7bb70eecf 100644 --- a/filters.py +++ b/filters.py @@ -97,8 +97,11 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: if wordsFile: wordsList = wordsFile.read().split('\n') for word in wordsList: - if word in content: - return True + if not word: + continue + if len(word) > 1: + if word in content: + return True if not nickname or not domain: return False From 7c6d7d158e1352220a0736e3d122cbdcb19f89be Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 13:10:32 +0000 Subject: [PATCH 49/88] Check minimum words length --- filters.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/filters.py b/filters.py index 7bb70eecf..408bd3604 100644 --- a/filters.py +++ b/filters.py @@ -27,6 +27,10 @@ def addGlobalFilter(baseDir: str, words: str) -> bool: """Adds a global filter for particular words within the content of a incoming posts """ + if not words: + return False + if len(words) < 2: + return False filtersFilename = baseDir + '/accounts/filters.txt' if os.path.isfile(filtersFilename): if words in open(filtersFilename).read(): From de1bfa8ed486e22c60b011e9a9d6f3e69a8035dc Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 13:21:06 +0000 Subject: [PATCH 50/88] Filtering base function So that global and account filtering are treated the same --- filters.py | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/filters.py b/filters.py index 408bd3604..06da9ce90 100644 --- a/filters.py +++ b/filters.py @@ -89,6 +89,29 @@ def isTwitterPost(content: str) -> bool: return False +def isFilteredBase(filename: str, content: str) -> bool: + """Uses the given file containing filtered words to check + the given content + """ + with open(filename, 'r') as fp: + for line in fp: + filterStr = line.replace('\n', '').replace('\r', '') + if not filterStr: + continue + if len(filterStr) < 2: + continue + if '+' not in filterStr: + if filterStr in content: + return True + else: + filterWords = filterStr.replace('"', '').split('+') + for word in filterWords: + if word not in content: + return False + return True + return False + + def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: """Should the given content be filtered out? This is a simple type of filter which just matches words, not a regex @@ -96,16 +119,8 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: words must be present although not necessarily adjacent """ globalFiltersFilename = baseDir + '/accounts/filters.txt' - if os.path.isfile(globalFiltersFilename): - wordsFile = open(globalFiltersFilename, 'r') - if wordsFile: - wordsList = wordsFile.read().split('\n') - for word in wordsList: - if not word: - continue - if len(word) > 1: - if word in content: - return True + if isFilteredBase(globalFiltersFilename, content): + return True if not nickname or not domain: return False @@ -119,17 +134,4 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool: accountFiltersFilename = baseDir + '/accounts/' + \ nickname + '@' + domain + '/filters.txt' - if os.path.isfile(accountFiltersFilename): - with open(accountFiltersFilename, 'r') as fp: - for line in fp: - filterStr = line.replace('\n', '').replace('\r', '') - if '+' not in filterStr: - if filterStr in content: - return True - else: - filterWords = filterStr.replace('"', '').split('+') - for word in filterWords: - if word not in content: - return False - return True - return False + return isFilteredBase(accountFiltersFilename, content) From b2658ebc31d6d6cedf91b9bd1d302eaf296e2ca1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 13:23:30 +0000 Subject: [PATCH 51/88] Check that file exists --- filters.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/filters.py b/filters.py index 06da9ce90..dc726ff55 100644 --- a/filters.py +++ b/filters.py @@ -93,6 +93,9 @@ def isFilteredBase(filename: str, content: str) -> bool: """Uses the given file containing filtered words to check the given content """ + if not os.path.isfile(filename): + return False + with open(filename, 'r') as fp: for line in fp: filterStr = line.replace('\n', '').replace('\r', '') From 99374a63dcf41e5768c4e6cbef1128c0a254948d Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 19 Dec 2020 14:17:30 +0000 Subject: [PATCH 52/88] Revert to previous wfRequest --- inbox.py | 14 ++++++++------ webapp_profile.py | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/inbox.py b/inbox.py index 424d47665..7c169f55e 100644 --- a/inbox.py +++ b/inbox.py @@ -174,12 +174,14 @@ def inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, if boxname != 'tlevents' and boxname != 'outbox': boxname = 'inbox' - wfRequest = {} - requestHandle = nickname + '@' + domain - if cachedWebfingers.get(requestHandle): - wfRequest = cachedWebfingers[requestHandle] - elif cachedWebfingers.get(requestHandle + ':' + str(port)): - wfRequest = cachedWebfingers[requestHandle + ':' + str(port)] + # wfRequest = {} + # requestHandle = nickname + '@' + domain + # if cachedWebfingers.get(requestHandle): + # wfRequest = cachedWebfingers[requestHandle] + # elif cachedWebfingers.get(requestHandle + ':' + str(port)): + # wfRequest = cachedWebfingers[requestHandle + ':' + str(port)] + # TODO: this may need to be changed + wfRequest = cachedWebfingers individualPostAsHtml(True, recentPostsCache, maxRecentPosts, translate, pageNumber, diff --git a/webapp_profile.py b/webapp_profile.py index 625c75c0a..29a8a6a77 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -261,12 +261,14 @@ def htmlProfileAfterSearch(cssCache: {}, if not item.get('object'): continue - wfRequest = {} - requestHandle = nickname + '@' + domain - if cachedWebfingers.get(requestHandle): - wfRequest = cachedWebfingers[requestHandle] - elif cachedWebfingers.get(requestHandle + ':' + str(port)): - wfRequest = cachedWebfingers[requestHandle + ':' + str(port)] + # wfRequest = {} + # requestHandle = nickname + '@' + domain + # if cachedWebfingers.get(requestHandle): + # wfRequest = cachedWebfingers[requestHandle] + # elif cachedWebfingers.get(requestHandle + ':' + str(port)): + # wfRequest = cachedWebfingers[requestHandle + ':' + str(port)] + # TODO: this may need to be changed + wfRequest = cachedWebfingers profileStr += \ individualPostAsHtml(True, recentPostsCache, maxRecentPosts, From fba6679b21a871f351c351faf2e81111be96eab6 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 11:00:17 +0000 Subject: [PATCH 53/88] List of accounts on moderator info screen --- epicyon-profile.css | 16 ++++++++++++ webapp_moderation.py | 62 +++++++++++++++++++++++++++++++++++++------- webapp_post.py | 27 +------------------ webapp_utils.py | 26 +++++++++++++++++++ 4 files changed, 95 insertions(+), 36 deletions(-) diff --git a/epicyon-profile.css b/epicyon-profile.css index 2e9436d3d..58c31101a 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -950,6 +950,14 @@ div.container { font-size: var(--font-size); color: var(--title-color); } + .accountsTable { + width: 100%; + border: 0; + } + .accountsTableCol { + width: 20%; + text-align: center; + } .containerHeader { border: var(--border-width-header) solid var(--border-color); background-color: var(--header-bg-color); @@ -1601,6 +1609,14 @@ div.container { font-size: var(--font-size-mobile); color: var(--title-color); } + .accountsTable { + width: 100%; + border: 0; + } + .accountsTableCol { + width: 20%; + text-align: center; + } .containerHeader { border: var(--border-width-header) solid var(--border-color); background-color: var(--header-bg-color); diff --git a/webapp_moderation.py b/webapp_moderation.py index 46c5ba634..79929ef2d 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -7,10 +7,12 @@ __email__ = "bob@freedombone.net" __status__ = "Production" import os +from utils import loadJson from utils import getNicknameFromActor from utils import getDomainFromActor from posts import getPublicPostInfo from webapp_timeline import htmlTimeline +# from webapp_utils import getPersonAvatarUrl from webapp_utils import getContentWarningButton from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlFooter @@ -152,11 +154,51 @@ def htmlModerationInfo(cssCache: {}, translate: {}, '

' infoShown = False + + cols = 5 + infoForm += '
\n' + infoForm += '\n' + infoForm += ' \n' + for col in range(cols): + infoForm += ' \n' + infoForm += ' \n' + infoForm += '\n' + col = 0 + for subdir, dirs, files in os.walk(baseDir + '/accounts'): + for acct in dirs: + if '@' not in acct: + continue + if 'inbox@' in acct or 'news@' in acct: + continue + accountDir = os.path.join(baseDir + '/accounts', acct) + acctNickname = acct.split('@')[0] + actorJson = loadJson(accountDir + '.json') + if not actorJson: + continue + actor = actorJson['id'] + avatarUrl = '' + if actorJson.get('icon'): + if actorJson['icon'].get('url'): + avatarUrl = actorJson['icon']['url'] + acctUrl = \ + '/users/' + nickname + '?options=' + actor + ';1;' + \ + avatarUrl.replace('/', '-') + infoForm += '\n' + col += 1 + if col == cols: + # new row of accounts + infoForm += '\n\n' + break + infoForm += '\n
\n' + infoForm += '' + infoForm += '
' + acctNickname + '
\n
\n' + infoForm += '
\n' + suspendedFilename = baseDir + '/accounts/suspended.txt' if os.path.isfile(suspendedFilename): with open(suspendedFilename, "r") as f: suspendedStr = f.read() - infoForm += '
' + infoForm += '
\n' infoForm += '
' + \ translate['Suspended accounts'] + '' infoForm += '
' + \ @@ -164,15 +206,15 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += \ ' ' - infoForm += '
' + suspendedStr + '\n' + infoForm += '
\n' infoShown = True blockingFilename = baseDir + '/accounts/blocking.txt' if os.path.isfile(blockingFilename): with open(blockingFilename, "r") as f: blockedStr = f.read() - infoForm += '
' + infoForm += '
\n' infoForm += \ '
' + \ translate['Blocked accounts and hashtags'] + '' @@ -182,29 +224,29 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += \ ' ' - infoForm += '
' + blockedStr + '\n' + infoForm += '
\n' infoShown = True filtersFilename = baseDir + '/accounts/filters.txt' if os.path.isfile(filtersFilename): with open(filtersFilename, "r") as f: filteredStr = f.read() - infoForm += '
' + infoForm += '
\n' infoForm += \ '
' + \ translate['Filtered words'] + '' infoForm += \ ' ' - infoForm += '
' + filteredStr + '\n' + infoForm += '
\n' infoShown = True if not infoShown: infoForm += \ '

' + \ translate[msgStr2] + \ - '

' + '

\n' infoForm += htmlFooter() return infoForm diff --git a/webapp_post.py b/webapp_post.py index 28891dca5..69a9eed4c 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -47,6 +47,7 @@ from content import getMentionsFromHtml from content import switchWords from person import isPersonSnoozed from announce import announcedByPerson +from webapp_utils import getAvatarImageUrl from webapp_utils import getPersonAvatarUrl from webapp_utils import updateAvatarImageCache from webapp_utils import loadIndividualPostAsHtmlFromCache @@ -177,32 +178,6 @@ def getPostFromRecentCache(session, return postHtml -def getAvatarImageUrl(session, - baseDir: str, httpPrefix: str, - postActor: str, personCache: {}, - avatarUrl: str, allowDownloads: bool) -> str: - """Returns the avatar image url - """ - # get the avatar image url for the post actor - if not avatarUrl: - avatarUrl = \ - getPersonAvatarUrl(baseDir, postActor, personCache, - allowDownloads) - avatarUrl = \ - updateAvatarImageCache(session, baseDir, httpPrefix, - postActor, avatarUrl, personCache, - allowDownloads) - else: - updateAvatarImageCache(session, baseDir, httpPrefix, - postActor, avatarUrl, personCache, - allowDownloads) - - if not avatarUrl: - avatarUrl = postActor + '/avatar.png' - - return avatarUrl - - def getAvatarImageHtml(showAvatarOptions: bool, nickname: str, domainFull: str, avatarUrl: str, postActor: str, diff --git a/webapp_utils.py b/webapp_utils.py index f70d76036..8003737ca 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -850,3 +850,29 @@ def htmlHighlightLabel(label: str, highlight: bool) -> str: if not highlight: return label return '*' + str(label) + '*' + + +def getAvatarImageUrl(session, + baseDir: str, httpPrefix: str, + postActor: str, personCache: {}, + avatarUrl: str, allowDownloads: bool) -> str: + """Returns the avatar image url + """ + # get the avatar image url for the post actor + if not avatarUrl: + avatarUrl = \ + getPersonAvatarUrl(baseDir, postActor, personCache, + allowDownloads) + avatarUrl = \ + updateAvatarImageCache(session, baseDir, httpPrefix, + postActor, avatarUrl, personCache, + allowDownloads) + else: + updateAvatarImageCache(session, baseDir, httpPrefix, + postActor, avatarUrl, personCache, + allowDownloads) + + if not avatarUrl: + avatarUrl = postActor + '/avatar.png' + + return avatarUrl From 2f2071f20958a5b8f9821ebacb0ee13f8e1be126 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 11:10:52 +0000 Subject: [PATCH 54/88] Image style --- epicyon-profile.css | 16 ++++++++-------- webapp_moderation.py | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/epicyon-profile.css b/epicyon-profile.css index 58c31101a..dbe620ade 100644 --- a/epicyon-profile.css +++ b/epicyon-profile.css @@ -951,12 +951,12 @@ div.container { color: var(--title-color); } .accountsTable { - width: 100%; - border: 0; + width: 100%; + border: 0; } .accountsTableCol { - width: 20%; - text-align: center; + width: 20%; + text-align: center; } .containerHeader { border: var(--border-width-header) solid var(--border-color); @@ -1610,12 +1610,12 @@ div.container { color: var(--title-color); } .accountsTable { - width: 100%; - border: 0; + width: 100%; + border: 0; } .accountsTableCol { - width: 20%; - text-align: center; + width: 20%; + text-align: center; } .containerHeader { border: var(--border-width-header) solid var(--border-color); diff --git a/webapp_moderation.py b/webapp_moderation.py index 79929ef2d..df880ba55 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -184,7 +184,7 @@ def htmlModerationInfo(cssCache: {}, translate: {}, '/users/' + nickname + '?options=' + actor + ';1;' + \ avatarUrl.replace('/', '-') infoForm += '\n' - infoForm += '' + infoForm += '' infoForm += '
' + acctNickname + '
\n\n' col += 1 if col == cols: From d312da3cfea5496f87c3915b0606f73226cc15bf Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 11:15:03 +0000 Subject: [PATCH 55/88] Avatars link --- webapp_moderation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index df880ba55..2ba253ff9 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -182,10 +182,11 @@ def htmlModerationInfo(cssCache: {}, translate: {}, avatarUrl = actorJson['icon']['url'] acctUrl = \ '/users/' + nickname + '?options=' + actor + ';1;' + \ - avatarUrl.replace('/', '-') + '/avatars/' + avatarUrl.replace('/', '-') infoForm += '\n' infoForm += '' - infoForm += '
' + acctNickname + '
\n\n' + infoForm += '
' + acctNickname + infoForm += '
\n\n' col += 1 if col == cols: # new row of accounts From 2d0fdc2f64d1d99390e12c114274cbc79d8ff9bd Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 11:31:29 +0000 Subject: [PATCH 56/88] Accounts in alphabetical order --- webapp_moderation.py | 50 +++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index 2ba253ff9..45401d380 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -163,35 +163,41 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += ' \n' infoForm += ' \n' infoForm += '\n' - col = 0 + accounts = [] for subdir, dirs, files in os.walk(baseDir + '/accounts'): for acct in dirs: if '@' not in acct: continue if 'inbox@' in acct or 'news@' in acct: continue - accountDir = os.path.join(baseDir + '/accounts', acct) - acctNickname = acct.split('@')[0] - actorJson = loadJson(accountDir + '.json') - if not actorJson: - continue - actor = actorJson['id'] - avatarUrl = '' - if actorJson.get('icon'): - if actorJson['icon'].get('url'): - avatarUrl = actorJson['icon']['url'] - acctUrl = \ - '/users/' + nickname + '?options=' + actor + ';1;' + \ - '/avatars/' + avatarUrl.replace('/', '-') - infoForm += '\n' - infoForm += '' - infoForm += '
' + acctNickname - infoForm += '
\n\n' - col += 1 - if col == cols: - # new row of accounts - infoForm += '\n\n' + accounts.append(acct) break + accounts.sort() + + col = 0 + for acct in accounts: + acctNickname = acct.split('@')[0] + accountDir = os.path.join(baseDir + '/accounts', acct) + actorJson = loadJson(accountDir + '.json') + if not actorJson: + continue + actor = actorJson['id'] + avatarUrl = '' + if actorJson.get('icon'): + if actorJson['icon'].get('url'): + avatarUrl = actorJson['icon']['url'] + acctUrl = \ + '/users/' + nickname + '?options=' + actor + ';1;' + \ + '/avatars/' + avatarUrl.replace('/', '-') + infoForm += '\n' + infoForm += '' + infoForm += '
' + acctNickname + infoForm += '
\n\n' + col += 1 + if col == cols: + # new row of accounts + infoForm += '\n\n' infoForm += '\n\n' infoForm += '\n' From 8f21dafc6b9789625c9be28dea9c1f65f0980b9d Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 11:51:23 +0000 Subject: [PATCH 57/88] If there are more than ten accounts then make them into a dropdown --- translations/ar.json | 3 ++- translations/ca.json | 3 ++- translations/cy.json | 3 ++- translations/de.json | 3 ++- translations/en.json | 3 ++- translations/es.json | 3 ++- translations/fr.json | 3 ++- translations/ga.json | 3 ++- translations/hi.json | 3 ++- translations/it.json | 3 ++- translations/ja.json | 3 ++- translations/oc.json | 3 ++- translations/pt.json | 3 ++- translations/ru.json | 3 ++- translations/zh.json | 3 ++- webapp_moderation.py | 22 ++++++++++++++-------- 16 files changed, 44 insertions(+), 23 deletions(-) diff --git a/translations/ar.json b/translations/ar.json index fabcebfb7..630067626 100644 --- a/translations/ar.json +++ b/translations/ar.json @@ -346,5 +346,6 @@ "Filter": "منقي", "Filter out words": "تصفية الكلمات", "Unfilter": "غير مرشح", - "Unfilter words": "الكلمات غير المصفاة" + "Unfilter words": "الكلمات غير المصفاة", + "Show Accounts": "إظهار الحسابات" } diff --git a/translations/ca.json b/translations/ca.json index 0953924e3..853f94914 100644 --- a/translations/ca.json +++ b/translations/ca.json @@ -346,5 +346,6 @@ "Filter": "Filtre", "Filter out words": "Filtra les paraules", "Unfilter": "Sense filtre", - "Unfilter words": "Paraules sense filtre" + "Unfilter words": "Paraules sense filtre", + "Show Accounts": "Mostra comptes" } diff --git a/translations/cy.json b/translations/cy.json index c387dc777..eafc25d65 100644 --- a/translations/cy.json +++ b/translations/cy.json @@ -346,5 +346,6 @@ "Filter": "Hidlo", "Filter out words": "Hidlo geiriau", "Unfilter": "Di-hid", - "Unfilter words": "Geiriau di-hid" + "Unfilter words": "Geiriau di-hid", + "Show Accounts": "Dangos Cyfrifon" } diff --git a/translations/de.json b/translations/de.json index 67658593e..6749671f9 100644 --- a/translations/de.json +++ b/translations/de.json @@ -346,5 +346,6 @@ "Filter": "Filter", "Filter out words": "Wörter herausfiltern", "Unfilter": "Filter entfernen", - "Unfilter words": "Wörter herausfiltern" + "Unfilter words": "Wörter herausfiltern", + "Show Accounts": "Konten anzeigen" } diff --git a/translations/en.json b/translations/en.json index 4d950d2d4..7dd037eb0 100644 --- a/translations/en.json +++ b/translations/en.json @@ -346,5 +346,6 @@ "Filter": "Filter", "Filter out words": "Filter out words", "Unfilter": "Unfilter", - "Unfilter words": "Unfilter words" + "Unfilter words": "Unfilter words", + "Show Accounts": "Show Accounts" } diff --git a/translations/es.json b/translations/es.json index 2f8c55025..dcf167a97 100644 --- a/translations/es.json +++ b/translations/es.json @@ -346,5 +346,6 @@ "Filter": "Filtrar", "Filter out words": "Filtrar palabras", "Unfilter": "Unfilter", - "Unfilter words": "Palabras sin filtrar" + "Unfilter words": "Palabras sin filtrar", + "Show Accounts": "Mostrar cuentas" } diff --git a/translations/fr.json b/translations/fr.json index 3a6db801f..3d8dc2b55 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -346,5 +346,6 @@ "Filter": "Filtre", "Filter out words": "Filtrer les mots", "Unfilter": "Non filtrer", - "Unfilter words": "Mots non filtrés" + "Unfilter words": "Mots non filtrés", + "Show Accounts": "Afficher les comptes" } diff --git a/translations/ga.json b/translations/ga.json index e35e11f71..a4e46b1f0 100644 --- a/translations/ga.json +++ b/translations/ga.json @@ -346,5 +346,6 @@ "Filter": "Scagaire", "Filter out words": "Scag focail amach", "Unfilter": "Neamhleithleach", - "Unfilter words": "Focail neamhleithleacha" + "Unfilter words": "Focail neamhleithleacha", + "Show Accounts": "Taispeáin Cuntais" } diff --git a/translations/hi.json b/translations/hi.json index 865de4a64..49f6d60e2 100644 --- a/translations/hi.json +++ b/translations/hi.json @@ -346,5 +346,6 @@ "Filter": "फ़िल्टर", "Filter out words": "शब्दों को फ़िल्टर करें", "Unfilter": "Unfilter", - "Unfilter words": "अनफ़िल्टर शब्द" + "Unfilter words": "अनफ़िल्टर शब्द", + "Show Accounts": "खाते दिखाएं" } diff --git a/translations/it.json b/translations/it.json index 27d3f500e..bd4b3db9c 100644 --- a/translations/it.json +++ b/translations/it.json @@ -346,5 +346,6 @@ "Filter": "Filtro", "Filter out words": "Filtra le parole", "Unfilter": "Unfilter", - "Unfilter words": "Parole non filtrate" + "Unfilter words": "Parole non filtrate", + "Show Accounts": "Mostra account" } diff --git a/translations/ja.json b/translations/ja.json index 1e290df23..e2029f181 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -346,5 +346,6 @@ "Filter": "フィルタ", "Filter out words": "単語を除外する", "Unfilter": "フィルタリング解除", - "Unfilter words": "単語のフィルタリングを解除する" + "Unfilter words": "単語のフィルタリングを解除する", + "Show Accounts": "アカウントを表示する" } diff --git a/translations/oc.json b/translations/oc.json index 1940d1b2c..dc474d00d 100644 --- a/translations/oc.json +++ b/translations/oc.json @@ -342,5 +342,6 @@ "Filter": "Filter", "Filter out words": "Filter out words", "Unfilter": "Unfilter", - "Unfilter words": "Unfilter words" + "Unfilter words": "Unfilter words", + "Show Accounts": "Show Accounts" } diff --git a/translations/pt.json b/translations/pt.json index f87b44705..b4cb1996a 100644 --- a/translations/pt.json +++ b/translations/pt.json @@ -346,5 +346,6 @@ "Filter": "Filtro", "Filter out words": "Filtrar palavras", "Unfilter": "Unfilter", - "Unfilter words": "Palavras sem filtro" + "Unfilter words": "Palavras sem filtro", + "Show Accounts": "Mostrar contas" } diff --git a/translations/ru.json b/translations/ru.json index a29f41750..a95083395 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -346,5 +346,6 @@ "Filter": "Фильтр", "Filter out words": "Отфильтровать слова", "Unfilter": "Нефильтровать", - "Unfilter words": "Не фильтровать слова" + "Unfilter words": "Не фильтровать слова", + "Show Accounts": "Показать счета" } diff --git a/translations/zh.json b/translations/zh.json index c2796f6e4..36ea2b053 100644 --- a/translations/zh.json +++ b/translations/zh.json @@ -346,5 +346,6 @@ "Filter": "过滤", "Filter out words": "过滤掉单词", "Unfilter": "取消过滤", - "Unfilter words": "未过滤字词" + "Unfilter words": "未过滤字词", + "Show Accounts": "显示帐户" } diff --git a/webapp_moderation.py b/webapp_moderation.py index 45401d380..2ac9298f1 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -155,14 +155,6 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoShown = False - cols = 5 - infoForm += '
\n' - infoForm += '\n' - infoForm += ' \n' - for col in range(cols): - infoForm += ' \n' - infoForm += ' \n' - infoForm += '\n' accounts = [] for subdir, dirs, files in os.walk(baseDir + '/accounts'): for acct in dirs: @@ -174,6 +166,18 @@ def htmlModerationInfo(cssCache: {}, translate: {}, break accounts.sort() + cols = 5 + if len(accounts) > 10: + infoForm += '
' + translate['Show Accounts'] + infoForm += '\n' + infoForm += '
\n' + infoForm += '
\n' + infoForm += ' \n' + for col in range(cols): + infoForm += ' \n' + infoForm += ' \n' + infoForm += '\n' + col = 0 for acct in accounts: acctNickname = acct.split('@')[0] @@ -200,6 +204,8 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '\n\n' infoForm += '\n
\n' infoForm += '
\n' + if len(accounts) > 10: + infoForm += '\n' suspendedFilename = baseDir + '/accounts/suspended.txt' if os.path.isfile(suspendedFilename): From 0c28e84eadcc70457fe37fb2727a59555f2791e2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:09:29 +0000 Subject: [PATCH 58/88] Highlight moderator accounts --- webapp_moderation.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index 2ac9298f1..2b6be3ee6 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -11,6 +11,7 @@ from utils import loadJson from utils import getNicknameFromActor from utils import getDomainFromActor from posts import getPublicPostInfo +from posts import isModerator from webapp_timeline import htmlTimeline # from webapp_utils import getPersonAvatarUrl from webapp_utils import getContentWarningButton @@ -196,7 +197,13 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '\n' infoForm += '' - infoForm += '
' + acctNickname + infoForm += '
' + modAccount = isModerator(baseDir, acctNickname) + if modAccount: + infoForm += '' + infoForm += acctNickname + if modAccount: + infoForm += '' infoForm += '
\n\n' col += 1 if col == cols: From d1658852fb67f371e5c3169c902df684b481321e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:11:45 +0000 Subject: [PATCH 59/88] Underline moderators --- webapp_moderation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index 2b6be3ee6..d4542e5e6 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -200,10 +200,10 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '
' modAccount = isModerator(baseDir, acctNickname) if modAccount: - infoForm += '' + infoForm += '' infoForm += acctNickname if modAccount: - infoForm += '' + infoForm += '' infoForm += '
\n\n' col += 1 if col == cols: From fb614c675d0eba33ccd9f0be715047205f970a95 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:34:16 +0000 Subject: [PATCH 60/88] Editor icon --- webapp_moderation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/webapp_moderation.py b/webapp_moderation.py index d4542e5e6..8139aecab 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net" __status__ = "Production" import os +from utils import isEditor from utils import loadJson from utils import getNicknameFromActor from utils import getDomainFromActor @@ -202,6 +203,8 @@ def htmlModerationInfo(cssCache: {}, translate: {}, if modAccount: infoForm += '' infoForm += acctNickname + if isEditor(baseDir, acctNickname): + infoForm += '✏' if modAccount: infoForm += '' infoForm += '
\n\n' From b7c4a140422f902b670647669028d49ca27a6e28 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:35:06 +0000 Subject: [PATCH 61/88] Space --- webapp_moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index 8139aecab..a7322ba85 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -204,7 +204,7 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '' infoForm += acctNickname if isEditor(baseDir, acctNickname): - infoForm += '✏' + infoForm += ' ✏' if modAccount: infoForm += '' infoForm += '\n\n' From 178d8698779a6a128a555a02b91afc1ae8db91d0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:35:56 +0000 Subject: [PATCH 62/88] Editor icon --- webapp_moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index a7322ba85..3eafc873a 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -204,7 +204,7 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '' infoForm += acctNickname if isEditor(baseDir, acctNickname): - infoForm += ' ✏' + infoForm += ' ✍' if modAccount: infoForm += '' infoForm += '\n\n' From 13ad1e57fbb243c63687ed46eb13227318c68ff0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:38:47 +0000 Subject: [PATCH 63/88] Simplify --- webapp_moderation.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index 3eafc873a..474988dd8 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -199,14 +199,12 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '' infoForm += '
' - modAccount = isModerator(baseDir, acctNickname) - if modAccount: - infoForm += '' - infoForm += acctNickname + if isModerator(baseDir, acctNickname) + infoForm += '' + acctNickname + '' + else: + infoForm += acctNickname if isEditor(baseDir, acctNickname): infoForm += ' ✍' - if modAccount: - infoForm += '' infoForm += '
\n\n' col += 1 if col == cols: From e42ba610c2f10c5eb673dd1c967d95ccb451520e Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 12:43:22 +0000 Subject: [PATCH 64/88] Missing colon --- webapp_moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index 474988dd8..216825855 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -199,7 +199,7 @@ def htmlModerationInfo(cssCache: {}, translate: {}, infoForm += '' infoForm += '
' - if isModerator(baseDir, acctNickname) + if isModerator(baseDir, acctNickname): infoForm += '' + acctNickname + '' else: infoForm += acctNickname From 5e6e2f80c5d35248580b74a7acca9a53cf922110 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 13:01:12 +0000 Subject: [PATCH 65/88] Displaying account avatars --- daemon.py | 6 ++++++ webapp_moderation.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index 35d8232f5..c7935efac 100644 --- a/daemon.py +++ b/daemon.py @@ -5084,6 +5084,12 @@ class PubServer(BaseHTTPRequestHandler): optionsActor = optionsList[0] optionsPageNumber = optionsList[1] optionsProfileUrl = optionsList[2] + if '.' in optionsProfileUrl and \ + optionsProfileUrl.startswith('/members/'): + ext = optionsProfileUrl.split('.')[-1] + optionsProfileUrl = optionsProfileUrl.split('/members/')[0] + optionsProfileUrl = \ + '/users/' + optionsProfileUrl + '/avatar.' + ext if optionsPageNumber.isdigit(): pageNumber = int(optionsPageNumber) optionsLink = None diff --git a/webapp_moderation.py b/webapp_moderation.py index 216825855..dcf2abd97 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -194,7 +194,7 @@ def htmlModerationInfo(cssCache: {}, translate: {}, avatarUrl = actorJson['icon']['url'] acctUrl = \ '/users/' + nickname + '?options=' + actor + ';1;' + \ - '/avatars/' + avatarUrl.replace('/', '-') + '/members/' + acctNickname infoForm += '\n' infoForm += '' From 2926b690ce294bf432fec0de3c4e0507097b6fac Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 13:24:22 +0000 Subject: [PATCH 66/88] Split index --- daemon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon.py b/daemon.py index c7935efac..5a601c19b 100644 --- a/daemon.py +++ b/daemon.py @@ -5087,7 +5087,7 @@ class PubServer(BaseHTTPRequestHandler): if '.' in optionsProfileUrl and \ optionsProfileUrl.startswith('/members/'): ext = optionsProfileUrl.split('.')[-1] - optionsProfileUrl = optionsProfileUrl.split('/members/')[0] + optionsProfileUrl = optionsProfileUrl.split('/members/')[1] optionsProfileUrl = \ '/users/' + optionsProfileUrl + '/avatar.' + ext if optionsPageNumber.isdigit(): From da256d24d2e12c12f3c2a6e17da6f036a51a7015 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 13:28:33 +0000 Subject: [PATCH 67/88] Get the avatar extension --- webapp_moderation.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index dcf2abd97..b5d0b3b28 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -189,12 +189,15 @@ def htmlModerationInfo(cssCache: {}, translate: {}, continue actor = actorJson['id'] avatarUrl = '' + ext = '' if actorJson.get('icon'): if actorJson['icon'].get('url'): avatarUrl = actorJson['icon']['url'] + if '.' in avatarUrl: + ext = avatarUrl.split('.')[-1] acctUrl = \ '/users/' + nickname + '?options=' + actor + ';1;' + \ - '/members/' + acctNickname + '/members/' + acctNickname + ext infoForm += '\n' infoForm += '' From c9376f0a2be3d2363f2c0f2cc145bf6550447bfb Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 13:30:55 +0000 Subject: [PATCH 68/88] Dot --- webapp_moderation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp_moderation.py b/webapp_moderation.py index b5d0b3b28..51e38e3dd 100644 --- a/webapp_moderation.py +++ b/webapp_moderation.py @@ -194,7 +194,7 @@ def htmlModerationInfo(cssCache: {}, translate: {}, if actorJson['icon'].get('url'): avatarUrl = actorJson['icon']['url'] if '.' in avatarUrl: - ext = avatarUrl.split('.')[-1] + ext = '.' + avatarUrl.split('.')[-1] acctUrl = \ '/users/' + nickname + '?options=' + actor + ';1;' + \ '/members/' + acctNickname + ext From 3a0644a2ae224eb015ab9eb7c9b5345cdc891fa0 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 13:36:20 +0000 Subject: [PATCH 69/88] Remove extension --- daemon.py | 1 + 1 file changed, 1 insertion(+) diff --git a/daemon.py b/daemon.py index 5a601c19b..5bf5fca8e 100644 --- a/daemon.py +++ b/daemon.py @@ -5088,6 +5088,7 @@ class PubServer(BaseHTTPRequestHandler): optionsProfileUrl.startswith('/members/'): ext = optionsProfileUrl.split('.')[-1] optionsProfileUrl = optionsProfileUrl.split('/members/')[1] + optionsProfileUrl = optionsProfileUrl.replace('.' + ext, '') optionsProfileUrl = \ '/users/' + optionsProfileUrl + '/avatar.' + ext if optionsPageNumber.isdigit(): From 42531e476fffb469d9b13019167c7ee7acffe41f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sun, 20 Dec 2020 13:54:54 +0000 Subject: [PATCH 70/88] Back button goes to moderation screen --- daemon.py | 4 +++- webapp_person_options.py | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/daemon.py b/daemon.py index 5bf5fca8e..6b8e61810 100644 --- a/daemon.py +++ b/daemon.py @@ -5091,6 +5091,7 @@ class PubServer(BaseHTTPRequestHandler): optionsProfileUrl = optionsProfileUrl.replace('.' + ext, '') optionsProfileUrl = \ '/users/' + optionsProfileUrl + '/avatar.' + ext + backToPath = 'moderation' if optionsPageNumber.isdigit(): pageNumber = int(optionsPageNumber) optionsLink = None @@ -5136,7 +5137,8 @@ class PubServer(BaseHTTPRequestHandler): toxAddress, jamiAddress, PGPpubKey, PGPfingerprint, emailAddress, - self.server.dormantMonths).encode('utf-8') + self.server.dormantMonths, + backToPath).encode('utf-8') self._set_headers('text/html', len(msg), cookie, callingDomain) self._write(msg) diff --git a/webapp_person_options.py b/webapp_person_options.py index 4d845eb2d..77f1d26f8 100644 --- a/webapp_person_options.py +++ b/webapp_person_options.py @@ -43,7 +43,8 @@ def htmlPersonOptions(defaultTimeline: str, PGPpubKey: str, PGPfingerprint: str, emailAddress: str, - dormantMonths: int) -> str: + dormantMonths: int, + backToPath: str) -> str: """Show options for a person: view/follow/block/report """ optionsDomain, optionsPort = getDomainFromActor(optionsActor) @@ -225,6 +226,8 @@ def htmlPersonOptions(defaultTimeline: str, backPath = '/' if nickname: backPath = '/users/' + nickname + '/' + defaultTimeline + if 'moderation' in backToPath: + backPath = '/users/' + nickname + '/moderation' optionsStr += \ '