diff --git a/epicyon.py b/epicyon.py index 0b9ffe78f..19db2a15c 100644 --- a/epicyon.py +++ b/epicyon.py @@ -113,7 +113,7 @@ parser.add_argument('--notificationType', '--notifyType', dest='notificationType', type=str, default='notify-send', help='Type of desktop notification command: ' + - 'notify-send/osascript/New-BurntToastNotification') + 'notify-send/zenity/osascript/New-BurntToastNotification') parser.add_argument('-o', '--onion', dest='onion', type=str, default=None, help='Onion domain name of the server if ' + diff --git a/notifications_client.py b/notifications_client.py index c8662d01f..2d3cc6d40 100644 --- a/notifications_client.py +++ b/notifications_client.py @@ -95,6 +95,10 @@ def _desktopNotification(notificationType: str, if notificationType == 'notify-send': # Ubuntu os.system('notify-send "' + title + '" "' + message + '"') + elif notificationType == 'zenity': + # Zenity + os.system('zenity --notification --title "' + title + + '" --text="' + message + '"') elif notificationType == 'osascript': # Mac os.system("osascript -e 'display notification \"" + @@ -118,14 +122,14 @@ def _textToSpeech(sayStr: str, screenreader: str, systemLanguage, sayStr) -def _sayCommand(sayStr: str, screenreader: str, +def _sayCommand(content: str, sayStr: str, screenreader: str, systemLanguage: str, espeak=None, speakerName='screen reader', speakerGender='They/Them') -> None: """Speaks a command """ - print(sayStr) + print(content) if not screenreader: return @@ -153,29 +157,30 @@ def _notificationReplyToPost(session, postId: str, toNickname = getNicknameFromActor(postId) toDomain, toPort = getDomainFromActor(postId) sayStr = 'Replying to ' + toNickname + '@' + toDomain - _sayCommand(sayStr, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sayStr = 'Type your reply message, then press Enter.' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) replyMessage = input() if not replyMessage: sayStr = 'No reply was entered.' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) return replyMessage = replyMessage.strip() if not replyMessage: sayStr = 'No reply was entered.' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) return sayStr = 'You entered this reply:' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) - _sayCommand(replyMessage, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) + _sayCommand(replyMessage, replyMessage, screenreader, + systemLanguage, espeak) sayStr = 'Send this reply, yes or no?' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) yesno = input() if 'y' not in yesno.lower(): sayStr = 'Abandoning reply' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) return ccUrl = None followersOnly = False @@ -186,7 +191,7 @@ def _notificationReplyToPost(session, postId: str, subject = None commentsEnabled = True sayStr = 'Sending reply' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) if sendPostViaServer(__version__, baseDir, session, nickname, password, domain, port, @@ -199,7 +204,7 @@ def _notificationReplyToPost(session, postId: str, sayStr = 'Reply sent' else: sayStr = 'Reply failed' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) def _notificationNewPost(session, @@ -212,28 +217,28 @@ def _notificationNewPost(session, """Use the notification client to create a new post """ sayStr = 'Create new post' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sayStr = 'Type your post, then press Enter.' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) newMessage = input() if not newMessage: sayStr = 'No post was entered.' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) return newMessage = newMessage.strip() if not newMessage: sayStr = 'No post was entered.' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) return sayStr = 'You entered this public post:' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) - _sayCommand(newMessage, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) + _sayCommand(newMessage, newMessage, screenreader, systemLanguage, espeak) sayStr = 'Send this post, yes or no?' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) yesno = input() if 'y' not in yesno.lower(): sayStr = 'Abandoning new post' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) return ccUrl = None followersOnly = False @@ -245,7 +250,7 @@ def _notificationNewPost(session, commentsEnabled = True subject = None sayStr = 'Sending' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) if sendPostViaServer(__version__, baseDir, session, nickname, password, domain, port, @@ -258,7 +263,7 @@ def _notificationNewPost(session, sayStr = 'Post sent' else: sayStr = 'Post failed' - _sayCommand(sayStr, screenreader, systemLanguage, espeak) + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, @@ -281,7 +286,7 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, return sayStr = 'Running ' + screenreader + ' for ' + nickname + '@' + domain - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) else: print('Running desktop notifications for ' + nickname + '@' + domain) @@ -289,10 +294,10 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, sayStr = 'Notification sounds on' else: sayStr = 'Notification sounds off' - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sayStr = '/q or /quit to exit' - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) print('') keyPress = _waitForKeypress(2, debug) @@ -410,15 +415,19 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, messageStr = speakerJson['say'] + '. ' + \ speakerJson['imageDescription'] + content = messageStr + if speakerJson.get('content'): + content = speakerJson['content'] + # say the speaker's name - _sayCommand(nameStr, screenreader, + _sayCommand(nameStr, nameStr, screenreader, systemLanguage, espeak, nameStr, gender) time.sleep(2) # speak the post content - _sayCommand(messageStr, screenreader, + _sayCommand(content, messageStr, screenreader, systemLanguage, espeak, nameStr, gender) @@ -433,7 +442,7 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, keyPress = keyPress[1:] if keyPress == 'q' or keyPress == 'quit' or keyPress == 'exit': sayStr = 'Quit' - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) if screenreader: keyPress = _waitForKeypress(2, debug) @@ -465,7 +474,8 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, print('') elif keyPress == 'like': if nameStr and gender and messageStr: - _sayCommand('Liking post by ' + nameStr, + sayStr = 'Liking post by ' + nameStr + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sessionLike = createSession(proxyType) @@ -478,7 +488,8 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, print('') elif keyPress == 'unlike' or keyPress == 'undo like': if nameStr and gender and messageStr: - _sayCommand('Undoing like of post by ' + nameStr, + sayStr = 'Undoing like of post by ' + nameStr + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sessionUnlike = createSession(proxyType) @@ -495,7 +506,8 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, if speakerJson.get('id'): if nameStr and gender and messageStr: postId = speakerJson['id'] - _sayCommand('Announcing post by ' + nameStr, + sayStr = 'Announcing post by ' + nameStr + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sessionAnnounce = createSession(proxyType) @@ -515,8 +527,9 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, followDomain, followPort = \ getDomainFromActor(followHandle) if followNickname and followDomain: - _sayCommand('Sending follow request to ' + - followNickname + '@' + followDomain, + sayStr = 'Sending follow request to ' + \ + followNickname + '@' + followDomain + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sessionFollow = createSession(proxyType) sendFollowRequestViaServer(baseDir, sessionFollow, @@ -530,7 +543,8 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, personCache, debug, __version__) else: - _sayCommand(followHandle + ' is not valid', + sayStr = followHandle + ' is not valid' + _sayCommand(sayStr, screenreader, systemLanguage, espeak) print('') elif (keyPress.startswith('unfollow ') or @@ -544,8 +558,9 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, followDomain, followPort = \ getDomainFromActor(followHandle) if followNickname and followDomain: - _sayCommand('Stop following ' + - followNickname + '@' + followDomain, + sayStr = 'Stop following ' + \ + followNickname + '@' + followDomain + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) sessionUnfollow = createSession(proxyType) sendUnfollowRequestViaServer(baseDir, sessionUnfollow, @@ -559,28 +574,30 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, personCache, debug, __version__) else: - _sayCommand(followHandle + ' is not valid', + sayStr = followHandle + ' is not valid' + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) print('') elif (keyPress == 'repeat' or keyPress == 'replay' or keyPress == 'rp'): - if nameStr and gender and messageStr: - _sayCommand('Repeating ' + nameStr, screenreader, + if nameStr and gender and messageStr and content: + sayStr = 'Repeating ' + nameStr, screenreader + _sayCommand(sayStr, sayStr, systemLanguage, espeak, nameStr, gender) time.sleep(2) - _sayCommand(messageStr, screenreader, + _sayCommand(content, messageStr, screenreader, systemLanguage, espeak, nameStr, gender) print('') elif keyPress == 'sounds on' or keyPress == 'sound': sayStr = 'Notification sounds on' - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) notificationSounds = True elif keyPress == 'sounds off' or keyPress == 'nosound': sayStr = 'Notification sounds off' - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) notificationSounds = False elif (keyPress == 'speak' or @@ -591,7 +608,7 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, if originalScreenReader: screenreader = originalScreenReader sayStr = 'Screen reader on' - _sayCommand(sayStr, screenreader, + _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) else: print('No --screenreader option was specified') @@ -603,7 +620,7 @@ def runNotificationsClient(baseDir: str, proxyType: str, httpPrefix: str, if originalScreenReader: screenreader = None sayStr = 'Screen reader off' - _sayCommand(sayStr, originalScreenReader, + _sayCommand(sayStr, sayStr, originalScreenReader, systemLanguage, espeak) else: print('No --screenreader option was specified') diff --git a/speaker.py b/speaker.py index b74d6a529..fef271773 100644 --- a/speaker.py +++ b/speaker.py @@ -274,18 +274,21 @@ def getSpeakerFromServer(baseDir: str, session, def _speakerEndpointJson(displayName: str, summary: str, - content: str, imageDescription: str, + content: str, sayContent: str, + imageDescription: str, links: [], gender: str, postId: str, postDM: bool, postReply: bool, followRequestsExist: bool, - likedBy: str, postCal: bool, + likedBy: str, published: str, postCal: bool, postShare: bool, themeName: str) -> {}: """Returns a json endpoint for the TTS speaker """ speakerJson = { "name": displayName, "summary": summary, - "say": content, + "content": content, + "say": sayContent, + "published": published, "imageDescription": imageDescription, "detectedLinks": links, "id": postId, @@ -412,11 +415,16 @@ def _postToSpeakerJson(baseDir: str, httpPrefix: str, content = content.replace(' <3', ' ' + translate['heart']) content = removeHtml(htmlReplaceQuoteMarks(content)) content = speakerReplaceLinks(content, translate, detectedLinks) - content = _speakerPronounce(baseDir, content, translate) # replace all double spaces while ' ' in content: content = content.replace(' ', ' ') - content = content.replace(' . ', '. ') + content = content.replace(' . ', '. ').strip() + sayContent = content + sayContent = _speakerPronounce(baseDir, content, translate) + # replace all double spaces + while ' ' in sayContent: + sayContent = sayContent.replace(' ', ' ') + sayContent = sayContent.replace(' . ', '. ').strip() imageDescription = '' if postJsonObject['object'].get('attachment'): @@ -430,6 +438,10 @@ def _postToSpeakerJson(baseDir: str, httpPrefix: str, imageDescription += \ img['name'] + '. ' + published = '' + if postJsonObject['object'].get('published'): + published = postJsonObject['object']['published'] + summary = '' if postJsonObject['object'].get('summary'): if isinstance(postJsonObject['object']['summary'], str): @@ -451,8 +463,9 @@ def _postToSpeakerJson(baseDir: str, httpPrefix: str, announcedDomain, announcedport = getDomainFromActor(announcingActor) if announcedNickname and announcedDomain: announcedHandle = announcedNickname + '@' + announcedDomain - content = \ - translate['announces'] + ' ' + announcedHandle + '. ' + content + sayContent = \ + translate['announces'] + ' ' + \ + announcedHandle + '. ' + sayContent postId = None if postJsonObject['object'].get('id'): postId = postJsonObject['object']['id'] @@ -484,11 +497,11 @@ def _postToSpeakerJson(baseDir: str, httpPrefix: str, postShare = os.path.isfile(shareFilename) return _speakerEndpointJson(speakerName, summary, - content, imageDescription, + content, sayContent, imageDescription, detectedLinks, gender, postId, postDM, postReply, followRequestsExist, - likedBy, + likedBy, published, postCal, postShare, themeName)