| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  | __filename__ = "speaker.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							|  |  |  | __version__ = "1.2.0" | 
					
						
							|  |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							| 
									
										
										
										
											2021-06-26 11:27:14 +00:00
										 |  |  | __module_group__ = "Accessibility" | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 12:39:18 +00:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | import html | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  | import random | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | import urllib.parse | 
					
						
							| 
									
										
										
										
											2021-03-12 14:34:56 +00:00
										 |  |  | from utils import isDM | 
					
						
							| 
									
										
										
										
											2021-03-16 12:59:43 +00:00
										 |  |  | from utils import isReply | 
					
						
							| 
									
										
										
										
											2021-03-03 20:34:55 +00:00
										 |  |  | from utils import camelCaseSplit | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | from utils import getDomainFromActor | 
					
						
							|  |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import getGenderFromBio | 
					
						
							|  |  |  | from utils import getDisplayName | 
					
						
							|  |  |  | from utils import removeHtml | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  | from utils import loadJson | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | from utils import saveJson | 
					
						
							| 
									
										
										
										
											2021-03-12 12:04:34 +00:00
										 |  |  | from utils import isPGPEncrypted | 
					
						
							| 
									
										
										
										
											2021-06-22 15:45:59 +00:00
										 |  |  | from utils import hasObjectDict | 
					
						
							| 
									
										
										
										
											2021-07-13 21:59:53 +00:00
										 |  |  | from utils import acctDir | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | from content import htmlReplaceQuoteMarks | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  | speakerRemoveChars = ('.\n', '. ', ',', ';', '?', '!') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 14:02:14 +00:00
										 |  |  | def getSpeakerPitch(displayName: str, screenreader: str, gender) -> int: | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  |     """Returns the speech synthesis pitch for the given name
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     random.seed(displayName) | 
					
						
							| 
									
										
										
										
											2021-03-03 14:02:14 +00:00
										 |  |  |     rangeMin = 1 | 
					
						
							|  |  |  |     rangeMax = 100 | 
					
						
							|  |  |  |     if 'She' in gender: | 
					
						
							|  |  |  |         rangeMin = 50 | 
					
						
							|  |  |  |     elif 'Him' in gender: | 
					
						
							|  |  |  |         rangeMax = 50 | 
					
						
							| 
									
										
										
										
											2021-03-02 15:13:10 +00:00
										 |  |  |     if screenreader == 'picospeaker': | 
					
						
							| 
									
										
										
										
											2021-03-03 20:19:56 +00:00
										 |  |  |         rangeMin = -6 | 
					
						
							| 
									
										
										
										
											2021-03-03 14:02:14 +00:00
										 |  |  |         rangeMax = 3 | 
					
						
							|  |  |  |         if 'She' in gender: | 
					
						
							|  |  |  |             rangeMin = -1 | 
					
						
							|  |  |  |         elif 'Him' in gender: | 
					
						
							|  |  |  |             rangeMax = -1 | 
					
						
							|  |  |  |     return random.randint(rangeMin, rangeMax) | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 15:13:10 +00:00
										 |  |  | def getSpeakerRate(displayName: str, screenreader: str) -> int: | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  |     """Returns the speech synthesis rate for the given name
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     random.seed(displayName) | 
					
						
							| 
									
										
										
										
											2021-03-02 15:13:10 +00:00
										 |  |  |     if screenreader == 'picospeaker': | 
					
						
							| 
									
										
										
										
											2021-03-03 21:21:17 +00:00
										 |  |  |         return random.randint(-40, -20) | 
					
						
							| 
									
										
										
										
											2021-03-01 19:16:33 +00:00
										 |  |  |     return random.randint(50, 120) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def getSpeakerRange(displayName: str) -> int: | 
					
						
							|  |  |  |     """Returns the speech synthesis range for the given name
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     random.seed(displayName) | 
					
						
							|  |  |  |     return random.randint(300, 800) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | def _speakerPronounce(baseDir: str, sayText: str, translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2021-03-02 12:39:18 +00:00
										 |  |  |     """Screen readers may not always pronounce correctly, so you
 | 
					
						
							|  |  |  |     can have a file which specifies conversions. File should contain | 
					
						
							|  |  |  |     line items such as: | 
					
						
							|  |  |  |     Epicyon -> Epi-cyon | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     pronounceFilename = baseDir + '/accounts/speaker_pronounce.txt' | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |     convertDict = {} | 
					
						
							|  |  |  |     if translate: | 
					
						
							|  |  |  |         convertDict = { | 
					
						
							|  |  |  |             "Epicyon": "Epi-cyon", | 
					
						
							|  |  |  |             "espeak": "e-speak", | 
					
						
							|  |  |  |             "emoji": "emowji", | 
					
						
							|  |  |  |             "clearnet": "clear-net", | 
					
						
							|  |  |  |             "https": "H-T-T-P-S", | 
					
						
							|  |  |  |             "HTTPS": "H-T-T-P-S", | 
					
						
							| 
									
										
										
										
											2021-03-03 20:41:22 +00:00
										 |  |  |             "XMPP": "X-M-P-P", | 
					
						
							|  |  |  |             "xmpp": "X-M-P-P", | 
					
						
							| 
									
										
										
										
											2021-03-03 22:26:54 +00:00
										 |  |  |             "sql": "S-Q-L", | 
					
						
							| 
									
										
										
										
											2021-03-08 22:02:54 +00:00
										 |  |  |             ".js": " dot J-S", | 
					
						
							| 
									
										
										
										
											2021-03-04 11:51:30 +00:00
										 |  |  |             "PSQL": "Postgres S-Q-L", | 
					
						
							| 
									
										
										
										
											2021-03-03 22:26:54 +00:00
										 |  |  |             "SQL": "S-Q-L", | 
					
						
							| 
									
										
										
										
											2021-03-11 12:44:47 +00:00
										 |  |  |             "gdpr": "G-D-P-R", | 
					
						
							| 
									
										
										
										
											2021-03-13 10:07:57 +00:00
										 |  |  |             "kde": "K-D-E", | 
					
						
							| 
									
										
										
										
											2021-03-14 11:17:37 +00:00
										 |  |  |             "AGPL": "Affearo G-P-L", | 
					
						
							|  |  |  |             "agpl": "Affearo G-P-L", | 
					
						
							|  |  |  |             "GPL": "G-P-L", | 
					
						
							|  |  |  |             "gpl": "G-P-L", | 
					
						
							| 
									
										
										
										
											2021-03-04 15:54:52 +00:00
										 |  |  |             "coop": "co-op", | 
					
						
							| 
									
										
										
										
											2021-03-04 11:51:30 +00:00
										 |  |  |             "KMail": "K-Mail", | 
					
						
							| 
									
										
										
										
											2021-03-13 10:10:02 +00:00
										 |  |  |             "kmail": "K-Mail", | 
					
						
							| 
									
										
										
										
											2021-03-04 11:51:30 +00:00
										 |  |  |             "gmail": "G-mail", | 
					
						
							|  |  |  |             "Gmail": "G-mail", | 
					
						
							|  |  |  |             "OpenPGP": "Open P-G-P", | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |             "Tor": "Toor", | 
					
						
							| 
									
										
										
										
											2021-03-10 18:44:44 +00:00
										 |  |  |             "memes": "meemes", | 
					
						
							|  |  |  |             "Memes": "Meemes", | 
					
						
							| 
									
										
										
										
											2021-03-10 20:43:02 +00:00
										 |  |  |             "rofl": "roll on the floor laughing", | 
					
						
							|  |  |  |             "ROFL": "roll on the floor laughing", | 
					
						
							| 
									
										
										
										
											2021-03-10 13:45:34 +00:00
										 |  |  |             "fwiw": "for what it's worth", | 
					
						
							|  |  |  |             "fyi": "for your information", | 
					
						
							| 
									
										
										
										
											2021-03-10 21:08:18 +00:00
										 |  |  |             "irl": "in real life", | 
					
						
							|  |  |  |             "IRL": "in real life", | 
					
						
							| 
									
										
										
										
											2021-03-10 13:45:34 +00:00
										 |  |  |             "imho": "in my opinion", | 
					
						
							| 
									
										
										
										
											2021-03-09 20:06:26 +00:00
										 |  |  |             "fediverse": "fediiverse", | 
					
						
							|  |  |  |             "Fediverse": "Fediiverse", | 
					
						
							| 
									
										
										
										
											2021-03-04 16:46:21 +00:00
										 |  |  |             " foss ": " free and open source software ", | 
					
						
							|  |  |  |             " floss ": " free libre and open source software ", | 
					
						
							|  |  |  |             " FOSS ": "free and open source software", | 
					
						
							|  |  |  |             " FLOSS ": "free libre and open source software", | 
					
						
							|  |  |  |             " oss ": " open source software ", | 
					
						
							|  |  |  |             " OSS ": " open source software ", | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |             "🤔": ". " + translate["thinking emoji"], | 
					
						
							|  |  |  |             "RT @": "Re-Tweet ", | 
					
						
							| 
									
										
										
										
											2021-03-03 20:56:35 +00:00
										 |  |  |             "#nowplaying": translate["hashtag"] + " now-playing", | 
					
						
							|  |  |  |             "#NowPlaying": translate["hashtag"] + " now-playing", | 
					
						
							| 
									
										
										
										
											2021-03-03 20:59:21 +00:00
										 |  |  |             "#": translate["hashtag"] + ' ', | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |             ":D": '. ' + translate["laughing"], | 
					
						
							|  |  |  |             ":-D": '. ' + translate["laughing"], | 
					
						
							|  |  |  |             ":)": '. ' + translate["smile"], | 
					
						
							|  |  |  |             ";)": '. ' + translate["wink"], | 
					
						
							|  |  |  |             ":(": '. ' + translate["sad face"], | 
					
						
							|  |  |  |             ":-)": '. ' + translate["smile"], | 
					
						
							|  |  |  |             ":-(": '. ' + translate["sad face"], | 
					
						
							|  |  |  |             ";-)": '. ' + translate["wink"], | 
					
						
							| 
									
										
										
										
											2021-03-10 10:43:53 +00:00
										 |  |  |             ":O": '. ' + translate['shocked'], | 
					
						
							| 
									
										
										
										
											2021-03-04 15:54:52 +00:00
										 |  |  |             "?": "? ", | 
					
						
							| 
									
										
										
										
											2021-03-04 16:20:24 +00:00
										 |  |  |             '"': "'", | 
					
						
							| 
									
										
										
										
											2021-03-03 21:30:01 +00:00
										 |  |  |             "*": "", | 
					
						
							|  |  |  |             "(": ",", | 
					
						
							|  |  |  |             ")": "," | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-02 12:39:18 +00:00
										 |  |  |     if os.path.isfile(pronounceFilename): | 
					
						
							| 
									
										
										
										
											2021-06-21 22:52:04 +00:00
										 |  |  |         with open(pronounceFilename, 'r') as fp: | 
					
						
							|  |  |  |             pronounceList = fp.readlines() | 
					
						
							| 
									
										
										
										
											2021-03-02 12:39:18 +00:00
										 |  |  |             for conversion in pronounceList: | 
					
						
							|  |  |  |                 separator = None | 
					
						
							|  |  |  |                 if '->' in conversion: | 
					
						
							|  |  |  |                     separator = '->' | 
					
						
							|  |  |  |                 elif ';' in conversion: | 
					
						
							|  |  |  |                     separator = ';' | 
					
						
							|  |  |  |                 elif ':' in conversion: | 
					
						
							|  |  |  |                     separator = ':' | 
					
						
							|  |  |  |                 elif ',' in conversion: | 
					
						
							|  |  |  |                     separator = ',' | 
					
						
							|  |  |  |                 if not separator: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 text = conversion.split(separator)[0].strip() | 
					
						
							|  |  |  |                 converted = conversion.split(separator)[1].strip() | 
					
						
							|  |  |  |                 convertDict[text] = converted | 
					
						
							|  |  |  |     for text, converted in convertDict.items(): | 
					
						
							|  |  |  |         if text in sayText: | 
					
						
							|  |  |  |             sayText = sayText.replace(text, converted) | 
					
						
							|  |  |  |     return sayText | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 21:26:34 +00:00
										 |  |  | def speakerReplaceLinks(sayText: str, translate: {}, | 
					
						
							|  |  |  |                         detectedLinks: []) -> str: | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |     """Replaces any links in the given text with "link to [domain]".
 | 
					
						
							|  |  |  |     Instead of reading out potentially very long and meaningless links | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     text = sayText | 
					
						
							| 
									
										
										
										
											2021-03-18 18:37:55 +00:00
										 |  |  |     text = text.replace('?v=', '__v=') | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |     for ch in speakerRemoveChars: | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |         text = text.replace(ch, ' ') | 
					
						
							| 
									
										
										
										
											2021-03-18 18:37:55 +00:00
										 |  |  |     text = text.replace('__v=', '?v=') | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |     replacements = {} | 
					
						
							|  |  |  |     wordsList = text.split(' ') | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |     if translate.get('Linked'): | 
					
						
							|  |  |  |         linkedStr = translate['Linked'] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         linkedStr = 'Linked' | 
					
						
							| 
									
										
										
										
											2021-03-02 14:05:43 +00:00
										 |  |  |     prevWord = '' | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |     for word in wordsList: | 
					
						
							| 
									
										
										
										
											2021-03-11 11:35:03 +00:00
										 |  |  |         if word.startswith('v='): | 
					
						
							| 
									
										
										
										
											2021-03-11 12:24:20 +00:00
										 |  |  |             replacements[word] = '' | 
					
						
							| 
									
										
										
										
											2021-03-02 16:50:32 +00:00
										 |  |  |         if word.startswith(':'): | 
					
						
							|  |  |  |             if word.endswith(':'): | 
					
						
							| 
									
										
										
										
											2021-03-02 17:18:47 +00:00
										 |  |  |                 replacements[word] = ', emowji ' + word.replace(':', '') + ',' | 
					
						
							| 
									
										
										
										
											2021-03-02 16:50:32 +00:00
										 |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2021-03-02 14:09:51 +00:00
										 |  |  |         if word.startswith('@') and not prevWord.endswith('RT'): | 
					
						
							| 
									
										
										
										
											2021-03-11 11:35:03 +00:00
										 |  |  |             # replace mentions, but not re-tweets | 
					
						
							| 
									
										
										
										
											2021-03-03 19:15:32 +00:00
										 |  |  |             if translate.get('mentioning'): | 
					
						
							|  |  |  |                 replacements[word] = \ | 
					
						
							| 
									
										
										
										
											2021-03-04 11:52:22 +00:00
										 |  |  |                     translate['mentioning'] + ' ' + word[1:] + ', ' | 
					
						
							| 
									
										
										
										
											2021-03-02 14:05:43 +00:00
										 |  |  |         prevWord = word | 
					
						
							| 
									
										
										
										
											2021-03-02 13:54:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |         domain = None | 
					
						
							|  |  |  |         domainFull = None | 
					
						
							|  |  |  |         if 'https://' in word: | 
					
						
							|  |  |  |             domain = word.split('https://')[1] | 
					
						
							|  |  |  |             domainFull = 'https://' + domain | 
					
						
							|  |  |  |         elif 'http://' in word: | 
					
						
							|  |  |  |             domain = word.split('http://')[1] | 
					
						
							|  |  |  |             domainFull = 'http://' + domain | 
					
						
							|  |  |  |         if not domain: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if '/' in domain: | 
					
						
							|  |  |  |             domain = domain.split('/')[0] | 
					
						
							| 
									
										
										
										
											2021-03-01 21:46:44 +00:00
										 |  |  |         if domain.startswith('www.'): | 
					
						
							|  |  |  |             domain = domain.replace('www.', '') | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |         replacements[domainFull] = '. ' + linkedStr + ' ' + domain + '.' | 
					
						
							| 
									
										
										
										
											2021-03-01 21:26:34 +00:00
										 |  |  |         detectedLinks.append(domainFull) | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  |     for replaceStr, newStr in replacements.items(): | 
					
						
							|  |  |  |         sayText = sayText.replace(replaceStr, newStr) | 
					
						
							| 
									
										
										
										
											2021-03-01 21:46:44 +00:00
										 |  |  |     return sayText.replace('..', '.') | 
					
						
							| 
									
										
										
										
											2021-03-01 21:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  | def _addSSMLemphasis(sayText: str) -> str: | 
					
						
							|  |  |  |     """Adds emphasis to *emphasised* text
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if '*' not in sayText: | 
					
						
							|  |  |  |         return sayText | 
					
						
							|  |  |  |     text = sayText | 
					
						
							|  |  |  |     for ch in speakerRemoveChars: | 
					
						
							|  |  |  |         text = text.replace(ch, ' ') | 
					
						
							|  |  |  |     wordsList = text.split(' ') | 
					
						
							|  |  |  |     replacements = {} | 
					
						
							|  |  |  |     for word in wordsList: | 
					
						
							|  |  |  |         if word.startswith('*'): | 
					
						
							|  |  |  |             if word.endswith('*'): | 
					
						
							|  |  |  |                 replacements[word] = \ | 
					
						
							|  |  |  |                     '<emphasis level="strong">' + \ | 
					
						
							|  |  |  |                     word.replace('*', '') + \ | 
					
						
							|  |  |  |                     '</emphasis>' | 
					
						
							|  |  |  |     for replaceStr, newStr in replacements.items(): | 
					
						
							|  |  |  |         sayText = sayText.replace(replaceStr, newStr) | 
					
						
							|  |  |  |     return sayText | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | def _removeEmojiFromText(sayText: str) -> str: | 
					
						
							| 
									
										
										
										
											2021-03-03 18:24:37 +00:00
										 |  |  |     """Removes :emoji: from the given text
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-03-03 20:18:14 +00:00
										 |  |  |     if ':' not in sayText: | 
					
						
							| 
									
										
										
										
											2021-03-03 18:24:37 +00:00
										 |  |  |         return sayText | 
					
						
							|  |  |  |     text = sayText | 
					
						
							|  |  |  |     for ch in speakerRemoveChars: | 
					
						
							|  |  |  |         text = text.replace(ch, ' ') | 
					
						
							|  |  |  |     wordsList = text.split(' ') | 
					
						
							|  |  |  |     replacements = {} | 
					
						
							|  |  |  |     for word in wordsList: | 
					
						
							|  |  |  |         if word.startswith(':'): | 
					
						
							|  |  |  |             if word.endswith(':'): | 
					
						
							| 
									
										
										
										
											2021-03-03 22:05:56 +00:00
										 |  |  |                 replacements[word] = '' | 
					
						
							| 
									
										
										
										
											2021-03-03 18:24:37 +00:00
										 |  |  |     for replaceStr, newStr in replacements.items(): | 
					
						
							|  |  |  |         sayText = sayText.replace(replaceStr, newStr) | 
					
						
							|  |  |  |     return sayText.replace('  ', ' ').strip() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | def _speakerEndpointJson(displayName: str, summary: str, | 
					
						
							| 
									
										
										
										
											2021-03-11 10:10:56 +00:00
										 |  |  |                          content: str, sayContent: str, | 
					
						
							|  |  |  |                          imageDescription: str, | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |                          links: [], gender: str, postId: str, | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |                          postDM: bool, postReply: bool, | 
					
						
							|  |  |  |                          followRequestsExist: bool, | 
					
						
							| 
									
										
										
										
											2021-03-15 20:23:17 +00:00
										 |  |  |                          followRequestsList: [], | 
					
						
							| 
									
										
										
										
											2021-03-11 10:15:25 +00:00
										 |  |  |                          likedBy: str, published: str, postCal: bool, | 
					
						
							| 
									
										
										
										
											2021-03-12 14:34:56 +00:00
										 |  |  |                          postShare: bool, themeName: str, | 
					
						
							| 
									
										
										
										
											2021-03-16 12:59:43 +00:00
										 |  |  |                          isDirect: bool, replyToYou: bool) -> {}: | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |     """Returns a json endpoint for the TTS speaker
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-03-03 13:02:47 +00:00
										 |  |  |     speakerJson = { | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |         "name": displayName, | 
					
						
							|  |  |  |         "summary": summary, | 
					
						
							| 
									
										
										
										
											2021-03-11 10:10:56 +00:00
										 |  |  |         "content": content, | 
					
						
							|  |  |  |         "say": sayContent, | 
					
						
							| 
									
										
										
										
											2021-03-11 10:15:25 +00:00
										 |  |  |         "published": published, | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |         "imageDescription": imageDescription, | 
					
						
							| 
									
										
										
										
											2021-03-04 10:34:23 +00:00
										 |  |  |         "detectedLinks": links, | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |         "id": postId, | 
					
						
							| 
									
										
										
										
											2021-03-12 14:34:56 +00:00
										 |  |  |         "direct": isDirect, | 
					
						
							| 
									
										
										
										
											2021-03-16 12:59:43 +00:00
										 |  |  |         "replyToYou": replyToYou, | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |         "notify": { | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |             "theme": themeName, | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |             "dm": postDM, | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |             "reply": postReply, | 
					
						
							|  |  |  |             "followRequests": followRequestsExist, | 
					
						
							| 
									
										
										
										
											2021-03-15 20:23:17 +00:00
										 |  |  |             "followRequestsList": followRequestsList, | 
					
						
							| 
									
										
										
										
											2021-03-09 16:58:57 +00:00
										 |  |  |             "likedBy": likedBy, | 
					
						
							|  |  |  |             "calendar": postCal, | 
					
						
							|  |  |  |             "share": postShare | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-03 13:02:47 +00:00
										 |  |  |     if gender: | 
					
						
							|  |  |  |         speakerJson['gender'] = gender | 
					
						
							|  |  |  |     return speakerJson | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 10:25:36 +00:00
										 |  |  | def _SSMLheader(systemLanguage: str, instanceTitle: str) -> str: | 
					
						
							|  |  |  |     """Returns a header for an SSML document
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '<?xml version="1.0"?>\n' + \ | 
					
						
							|  |  |  |         '<speak xmlns="http://www.w3.org/2001/10/synthesis"\n' + \ | 
					
						
							|  |  |  |         '       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + \ | 
					
						
							|  |  |  |         '       xsi:schemaLocation="http://www.w3.org/2001/10/synthesis\n' + \ | 
					
						
							|  |  |  |         '         http://www.w3.org/TR/speech-synthesis11/synthesis.xsd"\n' + \ | 
					
						
							|  |  |  |         '       version="1.1">\n' + \ | 
					
						
							|  |  |  |         '  <metadata>\n' + \ | 
					
						
							|  |  |  |         '    <dc:title xml:lang="' + systemLanguage + '">' + \ | 
					
						
							|  |  |  |         instanceTitle + ' inbox</dc:title>\n' + \ | 
					
						
							|  |  |  |         '  </metadata>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  | def _speakerEndpointSSML(displayName: str, summary: str, | 
					
						
							|  |  |  |                          content: str, imageDescription: str, | 
					
						
							|  |  |  |                          links: [], language: str, | 
					
						
							|  |  |  |                          instanceTitle: str, | 
					
						
							|  |  |  |                          gender: str) -> str: | 
					
						
							|  |  |  |     """Returns an SSML endpoint for the TTS speaker
 | 
					
						
							|  |  |  |     https://en.wikipedia.org/wiki/Speech_Synthesis_Markup_Language | 
					
						
							|  |  |  |     https://www.w3.org/TR/speech-synthesis/ | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     langShort = 'en' | 
					
						
							|  |  |  |     if language: | 
					
						
							|  |  |  |         langShort = language[:2] | 
					
						
							|  |  |  |     if not gender: | 
					
						
							|  |  |  |         gender = 'neutral' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         if langShort == 'en': | 
					
						
							|  |  |  |             gender = gender.lower() | 
					
						
							| 
									
										
										
										
											2021-03-03 13:02:47 +00:00
										 |  |  |             if 'he/him' in gender: | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |                 gender = 'male' | 
					
						
							| 
									
										
										
										
											2021-03-03 13:02:47 +00:00
										 |  |  |             elif 'she/her' in gender: | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |                 gender = 'female' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 gender = 'neutral' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     content = _addSSMLemphasis(content) | 
					
						
							|  |  |  |     voiceParams = 'name="' + displayName + '" gender="' + gender + '"' | 
					
						
							| 
									
										
										
										
											2021-03-04 10:25:36 +00:00
										 |  |  |     return _SSMLheader(langShort, instanceTitle) + \ | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |         '  <p>\n' + \ | 
					
						
							|  |  |  |         '    <s xml:lang="' + language + '">\n' + \ | 
					
						
							|  |  |  |         '      <voice ' + voiceParams + '>\n' + \ | 
					
						
							|  |  |  |         '        ' + content + '\n' + \ | 
					
						
							|  |  |  |         '      </voice>\n' + \ | 
					
						
							|  |  |  |         '    </s>\n' + \ | 
					
						
							|  |  |  |         '  </p>\n' + \ | 
					
						
							|  |  |  |         '</speak>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def getSSMLbox(baseDir: str, path: str, | 
					
						
							|  |  |  |                domain: str, | 
					
						
							|  |  |  |                systemLanguage: str, | 
					
						
							|  |  |  |                instanceTitle: str, | 
					
						
							|  |  |  |                boxName: str) -> str: | 
					
						
							|  |  |  |     """Returns SSML for the given timeline
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     nickname = path.split('/users/')[1] | 
					
						
							|  |  |  |     if '/' in nickname: | 
					
						
							|  |  |  |         nickname = nickname.split('/')[0] | 
					
						
							|  |  |  |     speakerFilename = \ | 
					
						
							| 
									
										
										
										
											2021-07-13 21:59:53 +00:00
										 |  |  |         acctDir(baseDir, nickname, domain) + '/speaker.json' | 
					
						
							| 
									
										
										
										
											2021-03-03 12:34:46 +00:00
										 |  |  |     if not os.path.isfile(speakerFilename): | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     speakerJson = loadJson(speakerFilename) | 
					
						
							|  |  |  |     if not speakerJson: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     gender = None | 
					
						
							|  |  |  |     if speakerJson.get('gender'): | 
					
						
							|  |  |  |         gender = speakerJson['gender'] | 
					
						
							|  |  |  |     return _speakerEndpointSSML(speakerJson['name'], | 
					
						
							|  |  |  |                                 speakerJson['summary'], | 
					
						
							|  |  |  |                                 speakerJson['say'], | 
					
						
							|  |  |  |                                 speakerJson['imageDescription'], | 
					
						
							|  |  |  |                                 speakerJson['detectedLinks'], | 
					
						
							|  |  |  |                                 systemLanguage, | 
					
						
							|  |  |  |                                 instanceTitle, gender) | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 19:04:58 +00:00
										 |  |  | def speakableText(baseDir: str, content: str, translate: {}) -> (str, []): | 
					
						
							| 
									
										
										
										
											2021-03-18 17:27:46 +00:00
										 |  |  |     """Convert the given text to a speakable version
 | 
					
						
							|  |  |  |     which includes changes for prononciation | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-03-25 14:51:41 +00:00
										 |  |  |     content = str(content) | 
					
						
							| 
									
										
										
										
											2021-03-18 17:27:46 +00:00
										 |  |  |     if isPGPEncrypted(content): | 
					
						
							| 
									
										
										
										
											2021-03-18 19:04:58 +00:00
										 |  |  |         return content, [] | 
					
						
							| 
									
										
										
										
											2021-03-18 17:27:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # replace some emoji before removing html | 
					
						
							|  |  |  |     if ' <3' in content: | 
					
						
							|  |  |  |         content = content.replace(' <3', ' ' + translate['heart']) | 
					
						
							|  |  |  |     content = removeHtml(htmlReplaceQuoteMarks(content)) | 
					
						
							|  |  |  |     detectedLinks = [] | 
					
						
							|  |  |  |     content = speakerReplaceLinks(content, translate, detectedLinks) | 
					
						
							|  |  |  |     # replace all double spaces | 
					
						
							|  |  |  |     while '  ' in content: | 
					
						
							|  |  |  |         content = content.replace('  ', ' ') | 
					
						
							|  |  |  |     content = content.replace(' . ', '. ').strip() | 
					
						
							|  |  |  |     sayContent = _speakerPronounce(baseDir, content, translate) | 
					
						
							|  |  |  |     # replace all double spaces | 
					
						
							|  |  |  |     while '  ' in sayContent: | 
					
						
							|  |  |  |         sayContent = sayContent.replace('  ', ' ') | 
					
						
							| 
									
										
										
										
											2021-03-18 19:04:58 +00:00
										 |  |  |     return sayContent.replace(' . ', '. ').strip(), detectedLinks | 
					
						
							| 
									
										
										
										
											2021-03-18 17:27:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  | def _postToSpeakerJson(baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                        nickname: str, domain: str, domainFull: str, | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  |                        postJsonObject: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |                        translate: {}, announcingActor: str, | 
					
						
							|  |  |  |                        themeName: str) -> {}: | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  |     """Converts an ActivityPub post into some Json containing
 | 
					
						
							|  |  |  |     speech synthesis parameters. | 
					
						
							|  |  |  |     NOTE: There currently appears to be no standardized json | 
					
						
							|  |  |  |     format for speech synthesis | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-06-22 15:45:59 +00:00
										 |  |  |     if not hasObjectDict(postJsonObject): | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  |         return | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('content'): | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if not isinstance(postJsonObject['object']['content'], str): | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     detectedLinks = [] | 
					
						
							|  |  |  |     content = urllib.parse.unquote_plus(postJsonObject['object']['content']) | 
					
						
							|  |  |  |     content = html.unescape(content) | 
					
						
							|  |  |  |     content = content.replace('<p>', '').replace('</p>', ' ') | 
					
						
							| 
									
										
										
										
											2021-03-12 12:04:34 +00:00
										 |  |  |     if not isPGPEncrypted(content): | 
					
						
							| 
									
										
										
										
											2021-03-11 17:15:32 +00:00
										 |  |  |         # replace some emoji before removing html | 
					
						
							|  |  |  |         if ' <3' in content: | 
					
						
							|  |  |  |             content = content.replace(' <3', ' ' + translate['heart']) | 
					
						
							|  |  |  |         content = removeHtml(htmlReplaceQuoteMarks(content)) | 
					
						
							|  |  |  |         content = speakerReplaceLinks(content, translate, detectedLinks) | 
					
						
							|  |  |  |         # replace all double spaces | 
					
						
							|  |  |  |         while '  ' in content: | 
					
						
							|  |  |  |             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() | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         sayContent = content | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     imageDescription = '' | 
					
						
							|  |  |  |     if postJsonObject['object'].get('attachment'): | 
					
						
							|  |  |  |         attachList = postJsonObject['object']['attachment'] | 
					
						
							|  |  |  |         if isinstance(attachList, list): | 
					
						
							|  |  |  |             for img in attachList: | 
					
						
							|  |  |  |                 if not isinstance(img, dict): | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if img.get('name'): | 
					
						
							|  |  |  |                     if isinstance(img['name'], str): | 
					
						
							|  |  |  |                         imageDescription += \ | 
					
						
							|  |  |  |                             img['name'] + '. ' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-12 14:34:56 +00:00
										 |  |  |     isDirect = isDM(postJsonObject) | 
					
						
							| 
									
										
										
										
											2021-03-16 12:59:43 +00:00
										 |  |  |     actor = httpPrefix + '://' + domainFull + '/users/' + nickname | 
					
						
							|  |  |  |     replyToYou = isReply(postJsonObject, actor) | 
					
						
							| 
									
										
										
										
											2021-03-12 14:34:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-11 10:15:25 +00:00
										 |  |  |     published = '' | 
					
						
							|  |  |  |     if postJsonObject['object'].get('published'): | 
					
						
							|  |  |  |         published = postJsonObject['object']['published'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  |     summary = '' | 
					
						
							|  |  |  |     if postJsonObject['object'].get('summary'): | 
					
						
							|  |  |  |         if isinstance(postJsonObject['object']['summary'], str): | 
					
						
							|  |  |  |             summary = \ | 
					
						
							|  |  |  |                 urllib.parse.unquote_plus(postJsonObject['object']['summary']) | 
					
						
							|  |  |  |             summary = html.unescape(summary) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     speakerName = \ | 
					
						
							|  |  |  |         getDisplayName(baseDir, postJsonObject['actor'], personCache) | 
					
						
							|  |  |  |     if not speakerName: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     speakerName = _removeEmojiFromText(speakerName) | 
					
						
							| 
									
										
										
										
											2021-03-03 20:22:18 +00:00
										 |  |  |     speakerName = speakerName.replace('_', ' ') | 
					
						
							| 
									
										
										
										
											2021-03-03 20:34:55 +00:00
										 |  |  |     speakerName = camelCaseSplit(speakerName) | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  |     gender = getGenderFromBio(baseDir, postJsonObject['actor'], | 
					
						
							|  |  |  |                               personCache, translate) | 
					
						
							|  |  |  |     if announcingActor: | 
					
						
							|  |  |  |         announcedNickname = getNicknameFromActor(announcingActor) | 
					
						
							| 
									
										
										
										
											2021-03-03 19:36:13 +00:00
										 |  |  |         announcedDomain, announcedport = getDomainFromActor(announcingActor) | 
					
						
							| 
									
										
										
										
											2021-03-03 19:31:23 +00:00
										 |  |  |         if announcedNickname and announcedDomain: | 
					
						
							|  |  |  |             announcedHandle = announcedNickname + '@' + announcedDomain | 
					
						
							| 
									
										
										
										
											2021-03-11 10:10:56 +00:00
										 |  |  |             sayContent = \ | 
					
						
							|  |  |  |                 translate['announces'] + ' ' + \ | 
					
						
							|  |  |  |                 announcedHandle + '. ' + sayContent | 
					
						
							| 
									
										
										
										
											2021-03-11 13:30:40 +00:00
										 |  |  |             content = \ | 
					
						
							|  |  |  |                 translate['announces'] + ' ' + \ | 
					
						
							|  |  |  |                 announcedHandle + '. ' + content | 
					
						
							| 
									
										
										
										
											2021-03-04 10:34:23 +00:00
										 |  |  |     postId = None | 
					
						
							|  |  |  |     if postJsonObject['object'].get('id'): | 
					
						
							|  |  |  |         postId = postJsonObject['object']['id'] | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |     followRequestsExist = False | 
					
						
							| 
									
										
										
										
											2021-03-15 20:23:17 +00:00
										 |  |  |     followRequestsList = [] | 
					
						
							| 
									
										
										
										
											2021-07-13 21:59:53 +00:00
										 |  |  |     accountsDir = acctDir(baseDir, nickname, domainFull) | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |     approveFollowsFilename = accountsDir + '/followrequests.txt' | 
					
						
							|  |  |  |     if os.path.isfile(approveFollowsFilename): | 
					
						
							| 
									
										
										
										
											2021-06-21 22:52:04 +00:00
										 |  |  |         with open(approveFollowsFilename, 'r') as fp: | 
					
						
							|  |  |  |             follows = fp.readlines() | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |             if len(follows) > 0: | 
					
						
							|  |  |  |                 followRequestsExist = True | 
					
						
							| 
									
										
										
										
											2021-03-15 20:45:41 +00:00
										 |  |  |                 for i in range(len(follows)): | 
					
						
							|  |  |  |                     follows[i] = follows[i].strip() | 
					
						
							| 
									
										
										
										
											2021-03-15 20:42:57 +00:00
										 |  |  |                 followRequestsList = follows | 
					
						
							| 
									
										
										
										
											2021-03-09 22:25:32 +00:00
										 |  |  |     postDM = False | 
					
						
							|  |  |  |     dmFilename = accountsDir + '/.newDM' | 
					
						
							|  |  |  |     if os.path.isfile(dmFilename): | 
					
						
							|  |  |  |         postDM = True | 
					
						
							|  |  |  |     postReply = False | 
					
						
							|  |  |  |     replyFilename = accountsDir + '/.newReply' | 
					
						
							|  |  |  |     if os.path.isfile(replyFilename): | 
					
						
							|  |  |  |         postReply = True | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |     likedBy = '' | 
					
						
							|  |  |  |     likeFilename = accountsDir + '/.newLike' | 
					
						
							|  |  |  |     if os.path.isfile(likeFilename): | 
					
						
							| 
									
										
										
										
											2021-06-21 22:52:04 +00:00
										 |  |  |         with open(likeFilename, 'r') as fp: | 
					
						
							|  |  |  |             likedBy = fp.read() | 
					
						
							| 
									
										
										
										
											2021-03-09 16:58:57 +00:00
										 |  |  |     calendarFilename = accountsDir + '/.newCalendar' | 
					
						
							|  |  |  |     postCal = os.path.isfile(calendarFilename) | 
					
						
							|  |  |  |     shareFilename = accountsDir + '/.newShare' | 
					
						
							|  |  |  |     postShare = os.path.isfile(shareFilename) | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  |     return _speakerEndpointJson(speakerName, summary, | 
					
						
							| 
									
										
										
										
											2021-03-11 10:10:56 +00:00
										 |  |  |                                 content, sayContent, imageDescription, | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |                                 detectedLinks, gender, postId, | 
					
						
							| 
									
										
										
										
											2021-03-09 15:01:35 +00:00
										 |  |  |                                 postDM, postReply, | 
					
						
							|  |  |  |                                 followRequestsExist, | 
					
						
							| 
									
										
										
										
											2021-03-15 20:23:17 +00:00
										 |  |  |                                 followRequestsList, | 
					
						
							| 
									
										
										
										
											2021-03-11 10:15:25 +00:00
										 |  |  |                                 likedBy, published, | 
					
						
							| 
									
										
										
										
											2021-03-12 14:34:56 +00:00
										 |  |  |                                 postCal, postShare, themeName, | 
					
						
							| 
									
										
										
										
											2021-03-16 12:59:43 +00:00
										 |  |  |                                 isDirect, replyToYou) | 
					
						
							| 
									
										
										
										
											2021-03-09 16:58:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  | def updateSpeaker(baseDir: str, httpPrefix: str, | 
					
						
							|  |  |  |                   nickname: str, domain: str, domainFull: str, | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  |                   postJsonObject: {}, personCache: {}, | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |                   translate: {}, announcingActor: str, | 
					
						
							|  |  |  |                   themeName: str) -> None: | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  |     """ Generates a json file which can be used for TTS announcement
 | 
					
						
							|  |  |  |     of incoming inbox posts | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     speakerJson = \ | 
					
						
							| 
									
										
										
										
											2021-03-09 13:52:02 +00:00
										 |  |  |         _postToSpeakerJson(baseDir, httpPrefix, | 
					
						
							|  |  |  |                            nickname, domain, domainFull, | 
					
						
							| 
									
										
										
										
											2021-03-04 10:11:30 +00:00
										 |  |  |                            postJsonObject, personCache, | 
					
						
							| 
									
										
										
										
											2021-03-09 19:52:10 +00:00
										 |  |  |                            translate, announcingActor, | 
					
						
							|  |  |  |                            themeName) | 
					
						
							| 
									
										
										
										
											2021-07-13 21:59:53 +00:00
										 |  |  |     speakerFilename = acctDir(baseDir, nickname, domain) + '/speaker.json' | 
					
						
							| 
									
										
										
										
											2021-03-03 19:06:18 +00:00
										 |  |  |     saveJson(speakerJson, speakerFilename) |