From 5d17c2d9ce6deccdbf09a4dd532999f4ddce50e1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Mon, 22 Mar 2021 23:03:23 +0000 Subject: [PATCH 01/17] Also check cc --- desktop_client.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/desktop_client.py b/desktop_client.py index 9bd3f5c98..def7ae183 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -182,11 +182,17 @@ def _postIsToYou(actor: str, postJsonObject: {}) -> bool: if postJsonObject.get('to'): if actor in postJsonObject['to']: toYourActor = True + if not toYourActor and postJsonObject.get('cc'): + if actor in postJsonObject['cc']: + toYourActor = True if not toYourActor and postJsonObject.get('object'): if isinstance(postJsonObject['object'], dict): if postJsonObject['object'].get('to'): if actor in postJsonObject['object']['to']: toYourActor = True + if not toYourActor and postJsonObject['object'].get('cc'): + if actor in postJsonObject['object']['cc']: + toYourActor = True return toYourActor From 1dda323ea72524646f928ecd0fb2e2db88b29bb1 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 09:43:42 +0000 Subject: [PATCH 02/17] Notification sounds optional --- desktop_client.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index def7ae183..575ffe1f0 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -1223,14 +1223,16 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, _desktopNotification(notificationType, "Epicyon", "New DM " + yourActor + '/dm') - _playNotificationSound(dmSoundFilename, player) + if notificationSounds: + _playNotificationSound(dmSoundFilename, player) if notifyJson.get('repliesNotify'): newRepliesExist = True if notifyJson.get('repliesNotifyChanged'): _desktopNotification(notificationType, "Epicyon", "New reply " + yourActor + '/replies') - _playNotificationSound(replySoundFilename, player) + if notificationSounds: + _playNotificationSound(replySoundFilename, player) if boxJson: timelineFirstId = _getFirstItemId(boxJson) From 6a31b0e9d710db8f5e4dd6def0527782bc8ca7f6 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 10:03:45 +0000 Subject: [PATCH 03/17] Improve notification logic --- desktop_client.py | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index 575ffe1f0..4c8fc6f4c 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -200,47 +200,47 @@ def _newDesktopNotifications(actor: str, inboxJson: {}, notifyJson: {}) -> None: """Looks for changes in the inbox and adds notifications """ + notifyJson['dmNotifyChanged'] = False + notifyJson['repliesNotifyChanged'] = False if not inboxJson: return if not inboxJson.get('orderedItems'): return - newDM = False - newReply = False - notifyJson['dmNotifyChanged'] = False - notifyJson['repliesNotifyChanged'] = False + DMdone = False + replyDone = False for postJsonObject in inboxJson['orderedItems']: if not postJsonObject.get('id'): continue if not _postIsToYou(actor, postJsonObject): continue - if 'dmNotify' not in notifyJson: - notifyJson['dmNotify'] = False if isDM(postJsonObject): - if not newDM: + if not DMdone: if not _hasReadPost(actor, postJsonObject['id'], 'dm'): - if notifyJson.get('dmPostId'): + changed = False + if not notifyJson.get('dmPostId'): + changed = True + else: if notifyJson['dmPostId'] != postJsonObject['id']: - notifyJson['dmNotify'] = True - notifyJson['dmNotifyChanged'] = True - newDM = True - else: - notifyJson['dmNotifyChanged'] = False - notifyJson['dmPostId'] = postJsonObject['id'] - if newDM: - break + changed = True + if changed: + notifyJson['dmNotify'] = True + notifyJson['dmNotifyChanged'] = True + notifyJson['dmPostId'] = postJsonObject['id'] + DMdone = True else: - if not newReply: + if not replyDone: if not _hasReadPost(actor, postJsonObject['id'], 'replies'): - if notifyJson.get('repliesPostId'): + changed = False + if not notifyJson.get('repliesPostId'): + changed = True + else: if notifyJson['repliesPostId'] != postJsonObject['id']: - notifyJson['repliesNotify'] = True - notifyJson['repliesNotifyChanged'] = True - newReply = True - else: - notifyJson['repliesNotifyChanged'] = False - notifyJson['repliesPostId'] = postJsonObject['id'] - if newReply: - break + changed = True + if changed: + notifyJson['repliesNotify'] = True + notifyJson['repliesNotifyChanged'] = True + notifyJson['repliesPostId'] = postJsonObject['id'] + replyDone = True def _desktopClearScreen() -> None: From eaf179f70483609fad4ab4f1fe5188aa7f172d4b Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 10:18:47 +0000 Subject: [PATCH 04/17] Space after full stop --- utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utils.py b/utils.py index ee51074fb..25e184efa 100644 --- a/utils.py +++ b/utils.py @@ -263,7 +263,9 @@ def removeHtml(content: str) -> str: removing = False elif not removing: result += ch - result = result.replace(' ', ' ').strip() + result = result.replace(' ', ' ') + result = result.replace('.', '. ') + result = result.replace(' ', ' ').strip() return result From dbad3f2fbd881c71720561f2a4eff64526509491 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 10:38:03 +0000 Subject: [PATCH 05/17] Adding spaces after full stops --- tests.py | 2 ++ utils.py | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tests.py b/tests.py index f66d6bb6f..233e8d029 100644 --- a/tests.py +++ b/tests.py @@ -2275,6 +2275,8 @@ def testRemoveHtml(): assert(removeHtml(testStr) == testStr) testStr = 'This string has html.' assert(removeHtml(testStr) == 'This string has html.') + testStr = '

This string has.

Two paragraphs.

' + assert(removeHtml(testStr) == 'This string has. Two paragraphs.') def testDangerousCSS(): diff --git a/utils.py b/utils.py index 25e184efa..16250f7d4 100644 --- a/utils.py +++ b/utils.py @@ -263,8 +263,18 @@ def removeHtml(content: str) -> str: removing = False elif not removing: result += ch - result = result.replace(' ', ' ') - result = result.replace('.', '. ') + + plainText = result.replace(' ', ' ') + + # insert spaces after full stops + strLen = len(plainText) + result = '' + for i in range(strLen): + result += plainText[i] + if plainText[i] == '.' and i < strLen - 1: + if plainText[i + 1] >= 'A' and plainText[i + 1] <= 'Z': + result += ' ' + result = result.replace(' ', ' ').strip() return result From e422d290217ec615c0c4dd89c2a1b78d9e1023f3 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 10:39:35 +0000 Subject: [PATCH 06/17] Marking posts as read --- desktop_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop_client.py b/desktop_client.py index 4c8fc6f4c..7f4df07de 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -673,7 +673,7 @@ def _readLocalBoxPost(session, nickname: str, domain: str, # if the post is addressed to you then mark it as read if _postIsToYou(yourActor, postJsonObject): - if isDM(postJsonObject['id']): + if isDM(postJsonObject): _markPostAsRead(yourActor, postJsonObject['id'], 'dm') else: _markPostAsRead(yourActor, postJsonObject['id'], 'replies') From 02cbf4a2b987cc78e0b90d4684d358d459be65be Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 10:52:10 +0000 Subject: [PATCH 07/17] Convert html paragraphs --- tests.py | 9 ++++++++- utils.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tests.py b/tests.py index 233e8d029..7c717143e 100644 --- a/tests.py +++ b/tests.py @@ -2275,8 +2275,15 @@ def testRemoveHtml(): assert(removeHtml(testStr) == testStr) testStr = 'This string has html.' assert(removeHtml(testStr) == 'This string has html.') + testStr = '' + assert(removeHtml(testStr) == 'This string has. Two labels.') testStr = '

This string has.

Two paragraphs.

' - assert(removeHtml(testStr) == 'This string has. Two paragraphs.') + assert(removeHtml(testStr) == 'This string has.\n\nTwo paragraphs.') + testStr = 'This string has.
A new line.' + assert(removeHtml(testStr) == 'This string has.\nA new line.') + testStr = '

This string contains a url http://somesite.or.other

' + assert(removeHtml(testStr) == \ + 'This string contains a url http://somesite.or.other') def testDangerousCSS(): diff --git a/utils.py b/utils.py index 16250f7d4..d349d11e5 100644 --- a/utils.py +++ b/utils.py @@ -255,6 +255,7 @@ def removeHtml(content: str) -> str: removing = False content = content.replace('', '"').replace('', '"') + content = content.replace('

', '\n\n').replace('
', '\n') result = '' for ch in content: if ch == '<': From 7b13d1e237887d0b8d883118f8d5fef7ef9ed030 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 10:56:11 +0000 Subject: [PATCH 08/17] Don't allow newlines in desktop client timeline --- desktop_client.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/desktop_client.py b/desktop_client.py index 7f4df07de..be6641f69 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -928,6 +928,8 @@ def _desktopShowBox(boxName: str, boxJson: {}, content = '🔇' if postJsonObject['object'].get('bookmarks'): content = '🔖' + content + if '\n' in content: + content = content.replace('\n', ' ') print(indent + str(posStr) + ' | ' + name + ' | ' + published + ' | ' + content) ctr += 1 From 5c1db157239d4f62c8d2ce709558e0f9c6055fac Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 11:22:09 +0000 Subject: [PATCH 09/17] Highlight inbox posts addressed to you --- desktop_client.py | 42 +++++++++++++++++++++++++++--------------- tests.py | 2 +- utils.py | 4 ++-- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index be6641f69..19f96c169 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -598,6 +598,7 @@ def _readLocalBoxPost(session, nickname: str, domain: str, ' from page ' + str(pageNumber) + '.' sayStr2 = sayStr.replace(' dm ', ' DM ') _sayCommand(sayStr, sayStr2, screenreader, systemLanguage, espeak) + print('') if postJsonObject['type'] == 'Announce': actor = postJsonObject['actor'] @@ -624,6 +625,7 @@ def _readLocalBoxPost(session, nickname: str, domain: str, sayStr = nameStr _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) + print('') if screenreader: time.sleep(2) content = \ @@ -660,6 +662,7 @@ def _readLocalBoxPost(session, nickname: str, domain: str, # say the speaker's name _sayCommand(nameStr, nameStr, screenreader, systemLanguage, espeak, nameStr, gender) + print('') if postJsonObject['object'].get('inReplyTo'): print('Replying to ' + postJsonObject['object']['inReplyTo'] + '\n') @@ -799,7 +802,7 @@ def _padToWidth(content: str, width: int) -> str: return content -def _desktopShowBox(boxName: str, boxJson: {}, +def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, screenreader: str, systemLanguage: str, espeak, pageNumber=1, newReplies=False, @@ -861,9 +864,14 @@ def _desktopShowBox(boxName: str, boxJson: {}, announcedDomain, announcedPort = \ getDomainFromActor(postJsonObject['object']) announcedHandle = announcedNickname + '@' + announcedDomain - print(indent + str(posStr) + ' | ' + name + ' | ' + - published + ' | ' + - _padToWidth(announcedHandle, contentWidth)) + lineStr = \ + indent + str(posStr) + ' | ' + name + ' | ' + \ + published + ' | ' + \ + _padToWidth(announcedHandle, contentWidth) + if boxName == 'inbox' and \ + _postIsToYou(yourActor, postJsonObject): + lineStr = '\33[7m' + lineStr + '\33[0m' + print(lineStr) ctr += 1 continue @@ -930,8 +938,12 @@ def _desktopShowBox(boxName: str, boxJson: {}, content = '🔖' + content if '\n' in content: content = content.replace('\n', ' ') - print(indent + str(posStr) + ' | ' + name + ' | ' + - published + ' | ' + content) + lineStr = indent + str(posStr) + ' | ' + name + ' | ' + \ + published + ' | ' + content + if boxName == 'inbox' and \ + _postIsToYou(yourActor, postJsonObject): + lineStr = '\33[7m' + lineStr + '\33[0m' + print(lineStr) ctr += 1 print('') @@ -1240,7 +1252,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, timelineFirstId = _getFirstItemId(boxJson) if timelineFirstId != prevTimelineFirstId: _desktopClearScreen() - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, None, systemLanguage, espeak, pageNumber, newRepliesExist, @@ -1278,7 +1290,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, currTimeline, pageNumber, debug) if boxJson: - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1293,7 +1305,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, currTimeline, pageNumber, debug) if boxJson: - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1309,7 +1321,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, currTimeline, pageNumber, debug) if boxJson: - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1326,7 +1338,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, currTimeline, pageNumber, debug) if boxJson: - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1351,7 +1363,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, currTimeline, pageNumber, debug) if boxJson: - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1361,7 +1373,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, else: postIndexStr = commandStr.split('read ')[1] if boxJson and postIndexStr.isdigit(): - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1379,7 +1391,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, else: postIndexStr = commandStr.split('profile ')[1] if boxJson and postIndexStr.isdigit(): - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) @@ -1924,7 +1936,7 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, if refreshTimeline: if boxJson: - _desktopShowBox(currTimeline, boxJson, + _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, newRepliesExist, newDMsExist) diff --git a/tests.py b/tests.py index 7c717143e..3eda974d4 100644 --- a/tests.py +++ b/tests.py @@ -2282,7 +2282,7 @@ def testRemoveHtml(): testStr = 'This string has.
A new line.' assert(removeHtml(testStr) == 'This string has.\nA new line.') testStr = '

This string contains a url http://somesite.or.other

' - assert(removeHtml(testStr) == \ + assert(removeHtml(testStr) == 'This string contains a url http://somesite.or.other') diff --git a/utils.py b/utils.py index d349d11e5..dc6ba6378 100644 --- a/utils.py +++ b/utils.py @@ -264,7 +264,7 @@ def removeHtml(content: str) -> str: removing = False elif not removing: result += ch - + plainText = result.replace(' ', ' ') # insert spaces after full stops @@ -276,7 +276,7 @@ def removeHtml(content: str) -> str: if plainText[i + 1] >= 'A' and plainText[i + 1] <= 'Z': result += ' ' - result = result.replace(' ', ' ').strip() + result = result.replace(' ', ' ').strip() return result From e7b7651f4892f1d89c572420dd64d33218d54470 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 14:16:44 +0000 Subject: [PATCH 10/17] Show who liked a post --- README_commandline.md | 2 + desktop_client.py | 96 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/README_commandline.md b/README_commandline.md index 57388b8ab..14e54a9ee 100644 --- a/README_commandline.md +++ b/README_commandline.md @@ -458,6 +458,8 @@ like Like the last post unlike Unlike the last post bookmark Bookmark the last post unbookmark Unbookmark the last post +block [post number|handle] Block someone via post number or handle +unblock [handle] Unblock someone mute Mute the last post unmute Unmute the last post reply Reply to the last post diff --git a/desktop_client.py b/desktop_client.py index 19f96c169..9fe2d3f0a 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -31,6 +31,8 @@ from like import sendLikeViaServer from like import sendUndoLikeViaServer from follow import sendFollowRequestViaServer from follow import sendUnfollowRequestViaServer +from posts import sendBlockViaServer +from posts import sendUndoBlockViaServer from posts import sendMuteViaServer from posts import sendUndoMuteViaServer from posts import sendPostViaServer @@ -78,6 +80,10 @@ def _desktopHelp() -> None: 'Bookmark the last post') print(indent + 'unbookmark ' + 'Unbookmark the last post') + print(indent + 'block [post number|handle] ' + + 'Block someone via post number or handle') + print(indent + 'unblock [handle] ' + + 'Unblock someone') print(indent + 'mute ' + 'Mute the last post') print(indent + 'unmute ' + @@ -674,6 +680,16 @@ def _readLocalBoxPost(session, nickname: str, domain: str, _sayCommand(content, messageStr, screenreader, systemLanguage, espeak, nameStr, gender) + if postJsonObject['object'].get('likes'): + if postJsonObject['object']['likes'].get('items'): + print('') + ctr = 0 + for item in postJsonObject['object']['likes']['items']: + print(' ❤ ' + str(item['actor'])) + ctr += 1 + if ctr >= 10: + break + # if the post is addressed to you then mark it as read if _postIsToYou(yourActor, postJsonObject): if isDM(postJsonObject): @@ -1627,6 +1643,86 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, False, __version__) refreshTimeline = True print('') + elif (commandStr.startswith('undo block ') or + commandStr.startswith('remove block ') or + commandStr.startswith('rm block ') or + commandStr.startswith('unblock ')): + currIndex = 0 + if ' ' in commandStr: + postIndex = commandStr.split(' ')[-1].strip() + if postIndex.isdigit(): + currIndex = int(postIndex) + if currIndex > 0 and boxJson: + postJsonObject = \ + _desktopGetBoxPostObject(boxJson, currIndex) + if postJsonObject: + if postJsonObject.get('id') and \ + postJsonObject.get('object'): + if isinstance(postJsonObject['object'], dict): + if postJsonObject['object'].get('attributedTo'): + blockActor = \ + postJsonObject['object']['attributedTo'] + sayStr = 'Unblocking ' + \ + getNicknameFromActor(blockActor) + _sayCommand(sayStr, sayStr, + screenreader, + systemLanguage, espeak) + sessionBlock = createSession(proxyType) + sendUndoBlockViaServer(baseDir, sessionBlock, + nickname, password, + domain, port, + httpPrefix, + blockActor, + cachedWebfingers, + personCache, + False, __version__) + refreshTimeline = True + print('') + elif commandStr.startswith('block '): + blockActor = None + currIndex = 0 + if ' ' in commandStr: + postIndex = commandStr.split(' ')[-1].strip() + if postIndex.isdigit(): + currIndex = int(postIndex) + else: + if '@' in postIndex: + blockHandle = postIndex + if blockHandle.startswith('@'): + blockHandle = blockHandle[1:] + if '@' in blockHandle: + blockDomain = blockHandle.split('@')[1] + blockNickname = blockHandle.split('@')[0] + blockActor = \ + httpPrefix + '://' + blockDomain + \ + '/users/' + blockNickname + if currIndex > 0 and boxJson and not blockActor: + postJsonObject = \ + _desktopGetBoxPostObject(boxJson, currIndex) + if postJsonObject and not blockActor: + if postJsonObject.get('id') and \ + postJsonObject.get('object'): + if isinstance(postJsonObject['object'], dict): + if postJsonObject['object'].get('attributedTo'): + blockActor = \ + postJsonObject['object']['attributedTo'] + if blockActor: + sayStr = 'Blocking ' + \ + getNicknameFromActor(blockActor) + _sayCommand(sayStr, sayStr, + screenreader, + systemLanguage, espeak) + sessionBlock = createSession(proxyType) + sendBlockViaServer(baseDir, sessionBlock, + nickname, password, + domain, port, + httpPrefix, + blockActor, + cachedWebfingers, + personCache, + False, __version__) + refreshTimeline = True + print('') elif commandStr == 'unlike' or commandStr == 'undo like': currIndex = 0 if ' ' in commandStr: From 5a178a28d68fba9fb62522fac4d7bf089d56035a Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 14:36:35 +0000 Subject: [PATCH 11/17] Tidying --- desktop_client.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index 9fe2d3f0a..d706f2876 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -580,6 +580,28 @@ def _getImageDescription(postJsonObject: {}) -> str: return imageDescription +def _showLikesOnPost(postJsonObject: {}, maxLikes: int) -> None: + """Shows the likes on a post + """ + if postJsonObject.get('object'): + return + if not isinstance(postJsonObject['object'], dict): + return + if not postJsonObject['object'].get('likes'): + return + if not isinstance(postJsonObject['object']['likes'], dict): + return + if not postJsonObject['object']['likes'].get('items'): + return + print('') + ctr = 0 + for item in postJsonObject['object']['likes']['items']: + print(' ❤ ' + str(item['actor'])) + ctr += 1 + if ctr >= maxLikes: + break + + def _readLocalBoxPost(session, nickname: str, domain: str, httpPrefix: str, baseDir: str, boxName: str, pageNumber: int, index: int, boxJson: {}, @@ -680,15 +702,7 @@ def _readLocalBoxPost(session, nickname: str, domain: str, _sayCommand(content, messageStr, screenreader, systemLanguage, espeak, nameStr, gender) - if postJsonObject['object'].get('likes'): - if postJsonObject['object']['likes'].get('items'): - print('') - ctr = 0 - for item in postJsonObject['object']['likes']['items']: - print(' ❤ ' + str(item['actor'])) - ctr += 1 - if ctr >= 10: - break + _showLikesOnPost(postJsonObject, 10) # if the post is addressed to you then mark it as read if _postIsToYou(yourActor, postJsonObject): From 7c58e89f0b08344929b26c65b38f9ac5e0230d75 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 14:50:40 +0000 Subject: [PATCH 12/17] Reverse logic --- desktop_client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/desktop_client.py b/desktop_client.py index d706f2876..bd636ffab 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -583,7 +583,7 @@ def _getImageDescription(postJsonObject: {}) -> str: def _showLikesOnPost(postJsonObject: {}, maxLikes: int) -> None: """Shows the likes on a post """ - if postJsonObject.get('object'): + if not postJsonObject.get('object'): return if not isinstance(postJsonObject['object'], dict): return @@ -593,6 +593,8 @@ def _showLikesOnPost(postJsonObject: {}, maxLikes: int) -> None: return if not postJsonObject['object']['likes'].get('items'): return + if not isinstance(postJsonObject['object']['likes']['items'], list): + return print('') ctr = 0 for item in postJsonObject['object']['likes']['items']: From a2c95ba9afda516d28f02f72812b3ee35399f87d Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 16:17:03 +0000 Subject: [PATCH 13/17] Show profile for last read post --- desktop_client.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index bd636ffab..6fff61856 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -721,16 +721,18 @@ def _showProfile(session, nickname: str, domain: str, pageNumber: int, index: int, boxJson: {}, systemLanguage: str, screenreader: str, espeak, - translate: {}, yourActor: str) -> {}: + translate: {}, yourActor: str, + postJsonObject: {}) -> {}: """Shows the profile of the actor for the given post Returns the actor json """ if _timelineIsEmpty(boxJson): return {} - postJsonObject = _desktopGetBoxPostObject(boxJson, index) if not postJsonObject: - return {} + postJsonObject = _desktopGetBoxPostObject(boxJson, index) + if not postJsonObject: + return {} actor = None if postJsonObject['type'] == 'Announce': @@ -1418,11 +1420,22 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, espeak, translate, yourActor) print('') elif commandStr.startswith('profile ') or commandStr == 'profile': + actorJson = None if commandStr == 'profile': - postIndexStr = '1' + if postJsonObject: + actorJson = \ + _showProfile(session, nickname, domain, + httpPrefix, baseDir, currTimeline, + pageNumber, postIndex, boxJson, + systemLanguage, screenreader, + espeak, translate, yourActor, + postJsonObject) + else: + postIndexStr = '1' else: postIndexStr = commandStr.split('profile ')[1] - if boxJson and postIndexStr.isdigit(): + + if not actorJson and boxJson and postIndexStr.isdigit(): _desktopShowBox(yourActor, currTimeline, boxJson, screenreader, systemLanguage, espeak, pageNumber, @@ -1433,7 +1446,8 @@ def runDesktopClient(baseDir: str, proxyType: str, httpPrefix: str, httpPrefix, baseDir, currTimeline, pageNumber, postIndex, boxJson, systemLanguage, screenreader, - espeak, translate, yourActor) + espeak, translate, yourActor, + None) print('') elif commandStr == 'reply' or commandStr == 'r': if postJsonObject: From 5f24d6cda45e215d0ff874f052b1b3d386d0f93d Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 19:14:49 +0000 Subject: [PATCH 14/17] Show replies --- daemon.py | 28 ++++++++++++---------------- desktop_client.py | 42 +++++++++++++++++++++++++++++++++++++++--- posts.py | 22 ++++++++++------------ 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/daemon.py b/daemon.py index adc1d81b4..48e0cf892 100644 --- a/daemon.py +++ b/daemon.py @@ -465,28 +465,24 @@ class PubServer(BaseHTTPRequestHandler): """ if postJsonObject.get('likes'): postJsonObject['likes'] = {'items': []} - if postJsonObject.get('shares'): - postJsonObject['shares'] = {} - if postJsonObject.get('replies'): - postJsonObject['replies'] = {} - if postJsonObject.get('bookmarks'): - postJsonObject['bookmarks'] = {} - if postJsonObject.get('ignores'): - postJsonObject['ignores'] = {} + + removeCollections = ( + 'shares', 'replies', 'bookmarks', 'ignores' + ) + for removeName in removeCollections: + if postJsonObject.get(removeName): + postJsonObject[removeName] = {} + if not postJsonObject.get('object'): return if not isinstance(postJsonObject['object'], dict): return if postJsonObject['object'].get('likes'): postJsonObject['object']['likes'] = {'items': []} - if postJsonObject['object'].get('shares'): - postJsonObject['object']['shares'] = {} - if postJsonObject['object'].get('replies'): - postJsonObject['object']['replies'] = {} - if postJsonObject['object'].get('bookmarks'): - postJsonObject['object']['bookmarks'] = {} - if postJsonObject['object'].get('ignores'): - postJsonObject['object']['ignores'] = {} + + for removeName in removeCollections: + if postJsonObject['object'].get(removeName): + postJsonObject['object'][removeName] = {} def _requestHTTP(self) -> bool: """Should a http response be given? diff --git a/desktop_client.py b/desktop_client.py index 6fff61856..719280451 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -217,6 +217,10 @@ def _newDesktopNotifications(actor: str, inboxJson: {}, for postJsonObject in inboxJson['orderedItems']: if not postJsonObject.get('id'): continue + if not postJsonObject.get('type'): + continue + if postJsonObject['type'] == 'Announce': + continue if not _postIsToYou(actor, postJsonObject): continue if isDM(postJsonObject): @@ -604,6 +608,32 @@ def _showLikesOnPost(postJsonObject: {}, maxLikes: int) -> None: break +def _showRepliesOnPost(postJsonObject: {}, maxReplies: int) -> None: + """Shows the replies on a post + """ + if not postJsonObject.get('object'): + return + if not isinstance(postJsonObject['object'], dict): + return + if not postJsonObject['object'].get('replies'): + return + if not isinstance(postJsonObject['object']['replies'], dict): + return + if not postJsonObject['object']['replies'].get('items'): + return + if not isinstance(postJsonObject['object']['replies']['items'], list): + return + print('') + ctr = 0 + print('Test 4638653 ' + str(postJsonObject['object']['replies']['items'])) + for item in postJsonObject['object']['replies']['items']: + print('Test 768235 ' + str(item)) + print(' ↰ ' + str(item['url'])) + ctr += 1 + if ctr >= maxReplies: + break + + def _readLocalBoxPost(session, nickname: str, domain: str, httpPrefix: str, baseDir: str, boxName: str, pageNumber: int, index: int, boxJson: {}, @@ -705,6 +735,7 @@ def _readLocalBoxPost(session, nickname: str, domain: str, systemLanguage, espeak, nameStr, gender) _showLikesOnPost(postJsonObject, 10) + _showRepliesOnPost(postJsonObject, 10) # if the post is addressed to you then mark it as read if _postIsToYou(yourActor, postJsonObject): @@ -902,9 +933,6 @@ def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, indent + str(posStr) + ' | ' + name + ' | ' + \ published + ' | ' + \ _padToWidth(announcedHandle, contentWidth) - if boxName == 'inbox' and \ - _postIsToYou(yourActor, postJsonObject): - lineStr = '\33[7m' + lineStr + '\33[0m' print(lineStr) ctr += 1 continue @@ -935,6 +963,14 @@ def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, spaceAdded = True name += ' ' name += '↲' + if postJsonObject['object'].get('replies'): + repliesList = postJsonObject['object']['replies'] + if repliesList.get('items'): + items = repliesList['items'] + for i in range(int(items)): + name += '↰' + if i > 10: + break likesCount = noOfLikes(postJsonObject) if likesCount > 10: likesCount = 10 diff --git a/posts.py b/posts.py index 74ea9133b..12d82a505 100644 --- a/posts.py +++ b/posts.py @@ -2885,15 +2885,15 @@ def createModeration(baseDir: str, nickname: str, domain: str, port: int, boxUrl = httpPrefix+'://'+domain+'/users/'+nickname+'/'+boxname boxHeader = { '@context': 'https://www.w3.org/ns/activitystreams', - 'first': boxUrl+'?page=true', + 'first': boxUrl + '?page=true', 'id': boxUrl, - 'last': boxUrl+'?page=true', + 'last': boxUrl + '?page=true', 'totalItems': 0, 'type': 'OrderedCollection' } boxItems = { '@context': 'https://www.w3.org/ns/activitystreams', - 'id': boxUrl+pageStr, + 'id': boxUrl + pageStr, 'orderedItems': [ ], 'partOf': boxUrl, @@ -3266,15 +3266,13 @@ def _createBoxIndexed(recentPostsCache: {}, if not isPublicPost(p): continue if p['object'].get('likes'): - p['likes'] = {'items': []} - if p['object'].get('replies'): - p['replies'] = {} - if p['object'].get('shares'): - p['shares'] = {} - if p['object'].get('bookmarks'): - p['bookmarks'] = {} - if p['object'].get('ignores'): - p['ignores'] = {} + p['object']['likes'] = {'items': []} + removeCollections = { + 'replies', 'shares', 'bookmarks', 'ignores' + } + for removeName in removeCollections: + if p['object'].get(removeName): + p['object'][removeName] = {} boxItems['orderedItems'].append(p) From ebb245354258e43b4b3738da9a4ea46b2682c6a5 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 22:52:00 +0000 Subject: [PATCH 15/17] Done earlier --- desktop_client.py | 6 ++---- inbox.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index 719280451..37488daa4 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -236,7 +236,7 @@ def _newDesktopNotifications(actor: str, inboxJson: {}, notifyJson['dmNotify'] = True notifyJson['dmNotifyChanged'] = True notifyJson['dmPostId'] = postJsonObject['id'] - DMdone = True + DMdone = True else: if not replyDone: if not _hasReadPost(actor, postJsonObject['id'], 'replies'): @@ -250,7 +250,7 @@ def _newDesktopNotifications(actor: str, inboxJson: {}, notifyJson['repliesNotify'] = True notifyJson['repliesNotifyChanged'] = True notifyJson['repliesPostId'] = postJsonObject['id'] - replyDone = True + replyDone = True def _desktopClearScreen() -> None: @@ -625,9 +625,7 @@ def _showRepliesOnPost(postJsonObject: {}, maxReplies: int) -> None: return print('') ctr = 0 - print('Test 4638653 ' + str(postJsonObject['object']['replies']['items'])) for item in postJsonObject['object']['replies']['items']: - print('Test 768235 ' + str(item)) print(' ↰ ' + str(item['url'])) ctr += 1 if ctr >= maxReplies: diff --git a/inbox.py b/inbox.py index 670275283..177c533e1 100644 --- a/inbox.py +++ b/inbox.py @@ -1593,12 +1593,32 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str, if debug: print('DEBUG: no domain found for ' + replyTo) return False + postFilename = locatePost(baseDir, replyToNickname, replyToDomain, replyTo) if not postFilename: if debug: print('DEBUG: post may have expired - ' + replyTo) return False + +# TODO store replies collection +# replyItem = { +# "type": "Document", +# "url": replyTo +# } +# if not messageJson['object'].get('replies'): +# messageJson['object']['replies'] = { +# "items": [replyItem] +# } +# else: +# found = False +# for item in messageJson['object']['replies']['items']: +# if item['url'] == replyTo: +# found = True +# break +# if not found: +# messageJson['object']['replies']['items'].append(replyItem) +# if not _postAllowsComments(postFilename): if debug: print('DEBUG: post does not allow comments - ' + replyTo) From 9e8045d047409a5722d3c2ea0b1eec124e9419a2 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 22:57:46 +0000 Subject: [PATCH 16/17] Check read status before highlighting --- desktop_client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/desktop_client.py b/desktop_client.py index 37488daa4..62980f3ab 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -1010,7 +1010,9 @@ def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, published + ' | ' + content if boxName == 'inbox' and \ _postIsToYou(yourActor, postJsonObject): - lineStr = '\33[7m' + lineStr + '\33[0m' + if not _hasReadPost(actor, postJsonObject['id'], 'dm'): + if not _hasReadPost(actor, postJsonObject['id'], 'replies'): + lineStr = '\33[7m' + lineStr + '\33[0m' print(lineStr) ctr += 1 From e982515043eef058cd152edd49e9aece6281f842 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 23 Mar 2021 23:33:33 +0000 Subject: [PATCH 17/17] Tidying --- desktop_client.py | 15 +++++++++++---- inbox.py | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index 62980f3ab..3347b967c 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -865,6 +865,12 @@ def _padToWidth(content: str, width: int) -> str: return content +def _highlightText(text: str) -> str: + """Returns a highlighted version of the given text + """ + return '\33[7m' + text + '\33[0m' + + def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, screenreader: str, systemLanguage: str, espeak, pageNumber=1, @@ -886,7 +892,7 @@ def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, boxNameStr = boxName[2:] else: boxNameStr = boxName - titleStr = '\33[7m' + boxNameStr.upper() + '\33[0m' + titleStr = _highlightText(boxNameStr.upper()) if newDMs: notificationIcons += ' 📩' @@ -1010,9 +1016,10 @@ def _desktopShowBox(yourActor: str, boxName: str, boxJson: {}, published + ' | ' + content if boxName == 'inbox' and \ _postIsToYou(yourActor, postJsonObject): - if not _hasReadPost(actor, postJsonObject['id'], 'dm'): - if not _hasReadPost(actor, postJsonObject['id'], 'replies'): - lineStr = '\33[7m' + lineStr + '\33[0m' + if not _hasReadPost(yourActor, postJsonObject['id'], 'dm'): + if not _hasReadPost(yourActor, postJsonObject['id'], + 'replies'): + lineStr = _highlightText(lineStr) print(lineStr) ctr += 1 diff --git a/inbox.py b/inbox.py index 177c533e1..864e5a1ac 100644 --- a/inbox.py +++ b/inbox.py @@ -1593,7 +1593,7 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str, if debug: print('DEBUG: no domain found for ' + replyTo) return False - + postFilename = locatePost(baseDir, replyToNickname, replyToDomain, replyTo) if not postFilename: