epicyon/desktop_client.py

2539 lines
112 KiB
Python
Raw Normal View History

2021-03-17 10:04:49 +00:00
__filename__ = "desktop_client.py"
2021-03-04 13:57:30 +00:00
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
2021-09-10 16:14:50 +00:00
__email__ = "bob@libreserver.org"
2021-03-04 13:57:30 +00:00
__status__ = "Production"
2021-06-15 15:08:12 +00:00
__module_group__ = "Client"
2021-03-04 13:57:30 +00:00
import os
import html
import time
2021-03-04 15:21:38 +00:00
import sys
import select
import webbrowser
import urllib.parse
from pathlib import Path
from random import randint
2021-12-26 11:29:40 +00:00
from utils import get_base_content_from_post
2021-12-26 10:57:03 +00:00
from utils import has_object_dict
2021-12-26 12:45:03 +00:00
from utils import get_full_domain
2021-12-26 20:12:18 +00:00
from utils import is_dm
2021-12-26 19:12:02 +00:00
from utils import load_translations_from_file
2021-12-27 15:43:22 +00:00
from utils import remove_html
2021-12-27 22:19:18 +00:00
from utils import get_nickname_from_actor
2021-12-27 19:05:25 +00:00
from utils import get_domain_from_actor
2021-12-26 19:15:36 +00:00
from utils import is_pgp_encrypted
2021-12-26 10:19:59 +00:00
from utils import local_actor_url
2021-12-28 16:56:57 +00:00
from session import create_session
2021-12-29 21:55:09 +00:00
from speaker import speakable_text
from speaker import get_speaker_pitch
from speaker import get_speaker_rate
from speaker import get_speaker_range
from like import send_like_via_server
from like import send_undo_like_via_server
from follow import approve_follow_request_via_server
from follow import deny_follow_request_via_server
from follow import get_follow_requests_via_server
from follow import get_following_via_server
from follow import get_followers_via_server
2021-12-28 20:32:11 +00:00
from follow import send_follow_requestViaServer
2021-12-29 21:55:09 +00:00
from follow import send_unfollow_request_via_server
from posts import send_block_via_server
from posts import send_undo_block_via_server
from posts import send_mute_via_server
from posts import send_undo_mute_via_server
from posts import send_post_via_server
from posts import c2s_box_json
from posts import download_announce
from announce import send_announce_via_server
from announce import send_undo_announce_via_server
from pgp import pgp_local_public_key
from pgp import pgp_decrypt
from pgp import has_local_pg_pkey
from pgp import pgp_encrypt_to_actor
from pgp import pgp_public_key_upload
from like import no_of_likes
from bookmarks import send_bookmark_via_server
from bookmarks import send_undo_bookmark_via_server
from delete import send_delete_via_server
from person import get_actor_json
def _desktop_help() -> None:
2021-03-16 23:10:14 +00:00
"""Shows help
"""
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
2021-03-16 23:14:34 +00:00
indent = ' '
2021-03-16 23:10:14 +00:00
print('')
2021-12-29 21:55:09 +00:00
print(indent + _highlight_text('Help Commands:'))
2021-03-16 23:10:14 +00:00
print('')
2021-03-19 21:34:38 +00:00
print(indent + 'quit ' +
2021-03-17 10:04:49 +00:00
'Exit from the desktop client')
2021-03-19 21:34:38 +00:00
print(indent + 'show dm|sent|inbox|replies|bookmarks ' +
2021-03-16 23:14:34 +00:00
'Show a timeline')
2021-03-19 21:34:38 +00:00
print(indent + 'mute ' +
2021-03-16 23:14:34 +00:00
'Turn off the screen reader')
2021-03-19 21:34:38 +00:00
print(indent + 'speak ' +
2021-03-16 23:14:34 +00:00
'Turn on the screen reader')
2021-03-19 21:34:38 +00:00
print(indent + 'sounds on ' +
2021-03-16 23:14:34 +00:00
'Turn on notification sounds')
2021-03-19 21:34:38 +00:00
print(indent + 'sounds off ' +
2021-03-16 23:14:34 +00:00
'Turn off notification sounds')
2021-03-19 21:34:38 +00:00
print(indent + 'rp ' +
2021-03-16 23:14:34 +00:00
'Repeat the last post')
2021-03-19 21:34:38 +00:00
print(indent + 'like ' +
2021-03-16 23:14:34 +00:00
'Like the last post')
2021-03-19 21:34:38 +00:00
print(indent + 'unlike ' +
2021-03-16 23:14:34 +00:00
'Unlike the last post')
2021-03-20 09:49:43 +00:00
print(indent + 'bookmark ' +
2021-03-21 12:31:48 +00:00
'Bookmark the last post')
2021-03-20 09:49:43 +00:00
print(indent + 'unbookmark ' +
'Unbookmark the last post')
2021-03-23 14:16:44 +00:00
print(indent + 'block [post number|handle] ' +
'Block someone via post number or handle')
print(indent + 'unblock [handle] ' +
'Unblock someone')
2021-03-21 12:31:48 +00:00
print(indent + 'mute ' +
'Mute the last post')
print(indent + 'unmute ' +
'Unmute the last post')
2021-03-19 21:34:38 +00:00
print(indent + 'reply ' +
2021-03-16 23:14:34 +00:00
'Reply to the last post')
2021-03-19 21:34:38 +00:00
print(indent + 'post ' +
2021-03-16 23:14:34 +00:00
'Create a new post')
2021-03-19 21:34:38 +00:00
print(indent + 'post to [handle] ' +
2021-03-16 23:14:34 +00:00
'Create a new direct message')
2021-03-19 21:34:38 +00:00
print(indent + 'announce/boost ' +
2021-03-16 23:14:34 +00:00
'Boost the last post')
2021-03-19 21:34:38 +00:00
print(indent + 'follow [handle] ' +
2021-03-16 23:14:34 +00:00
'Make a follow request')
2021-03-19 21:34:38 +00:00
print(indent + 'unfollow [handle] ' +
2021-03-16 23:14:34 +00:00
'Stop following the give handle')
2021-03-19 21:34:38 +00:00
print(indent + 'next ' +
2021-03-16 23:14:34 +00:00
'Next page in the timeline')
2021-03-19 21:34:38 +00:00
print(indent + 'prev ' +
2021-03-16 23:14:34 +00:00
'Previous page in the timeline')
2021-03-19 21:34:38 +00:00
print(indent + 'read [post number] ' +
2021-03-16 23:14:34 +00:00
'Read a post from a timeline')
2021-03-19 21:34:38 +00:00
print(indent + 'open [post number] ' +
2021-03-16 23:14:34 +00:00
'Open web links within a timeline post')
2021-03-25 12:57:01 +00:00
print(indent + 'profile [post number or handle] ' +
2021-03-22 18:27:48 +00:00
'Show profile for the person who made the given post')
print(indent + 'following [page number] ' +
'Show accounts that you are following')
print(indent + 'followers [page number] ' +
'Show accounts that are following you')
print(indent + 'approve [handle] ' +
'Approve a follow request')
print(indent + 'deny [handle] ' +
'Deny a follow request')
2021-05-05 09:53:00 +00:00
print(indent + 'pgp ' +
'Show your PGP public key')
2021-03-16 23:10:14 +00:00
print('')
2021-12-29 21:55:09 +00:00
def _create_desktop_config(actor: str) -> None:
"""Sets up directories for desktop client configuration
"""
homeDir = str(Path.home())
if not os.path.isdir(homeDir + '/.config'):
os.mkdir(homeDir + '/.config')
if not os.path.isdir(homeDir + '/.config/epicyon'):
os.mkdir(homeDir + '/.config/epicyon')
2021-12-27 22:19:18 +00:00
nickname = get_nickname_from_actor(actor)
2021-12-27 19:05:25 +00:00
domain, port = get_domain_from_actor(actor)
handle = nickname + '@' + domain
if port != 443 and port != 80:
handle += '_' + str(port)
readPostsDir = homeDir + '/.config/epicyon/' + handle
if not os.path.isdir(readPostsDir):
os.mkdir(readPostsDir)
2021-12-29 21:55:09 +00:00
def _mark_post_as_read(actor: str, post_id: str, postCategory: str) -> None:
"""Marks the given post as read by the given actor
"""
homeDir = str(Path.home())
2021-12-29 21:55:09 +00:00
_create_desktop_config(actor)
2021-12-27 22:19:18 +00:00
nickname = get_nickname_from_actor(actor)
2021-12-27 19:05:25 +00:00
domain, port = get_domain_from_actor(actor)
handle = nickname + '@' + domain
if port != 443 and port != 80:
handle += '_' + str(port)
readPostsDir = homeDir + '/.config/epicyon/' + handle
readPostsFilename = readPostsDir + '/' + postCategory + '.txt'
if os.path.isfile(readPostsFilename):
2021-12-26 19:47:06 +00:00
if post_id in open(readPostsFilename).read():
return
try:
# prepend to read posts file
2021-12-26 19:47:06 +00:00
post_id += '\n'
with open(readPostsFilename, 'r+') as readFile:
content = readFile.read()
2021-12-26 19:47:06 +00:00
if post_id not in content:
readFile.seek(0, 0)
2021-12-26 19:47:06 +00:00
readFile.write(post_id + content)
2021-12-25 15:28:52 +00:00
except Exception as ex:
print('WARN: Failed to mark post as read' + str(ex))
else:
2021-06-22 12:27:10 +00:00
with open(readPostsFilename, 'w+') as readFile:
2021-12-26 19:47:06 +00:00
readFile.write(post_id + '\n')
2021-12-29 21:55:09 +00:00
def _has_read_post(actor: str, post_id: str, postCategory: str) -> bool:
"""Returns true if the given post has been read by the actor
"""
homeDir = str(Path.home())
2021-12-29 21:55:09 +00:00
_create_desktop_config(actor)
2021-12-27 22:19:18 +00:00
nickname = get_nickname_from_actor(actor)
2021-12-27 19:05:25 +00:00
domain, port = get_domain_from_actor(actor)
handle = nickname + '@' + domain
if port != 443 and port != 80:
handle += '_' + str(port)
readPostsDir = homeDir + '/.config/epicyon/' + handle
readPostsFilename = readPostsDir + '/' + postCategory + '.txt'
if os.path.isfile(readPostsFilename):
2021-12-26 19:47:06 +00:00
if post_id in open(readPostsFilename).read():
return True
return False
2021-12-29 21:55:09 +00:00
def _post_is_to_you(actor: str, post_json_object: {}) -> bool:
"""Returns true if the post is to the actor
"""
toYourActor = False
2021-12-25 22:09:19 +00:00
if post_json_object.get('to'):
if actor in post_json_object['to']:
toYourActor = True
2021-12-25 22:09:19 +00:00
if not toYourActor and post_json_object.get('cc'):
if actor in post_json_object['cc']:
2021-03-22 23:03:23 +00:00
toYourActor = True
2021-12-26 10:57:03 +00:00
if not toYourActor and has_object_dict(post_json_object):
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('to'):
if actor in post_json_object['object']['to']:
toYourActor = True
2021-12-25 22:09:19 +00:00
if not toYourActor and post_json_object['object'].get('cc'):
if actor in post_json_object['object']['cc']:
toYourActor = True
return toYourActor
2021-12-29 21:55:09 +00:00
def _new_desktop_notifications(actor: str, inboxJson: {},
notifyJson: {}) -> None:
"""Looks for changes in the inbox and adds notifications
"""
2021-03-23 10:03:45 +00:00
notifyJson['dmNotifyChanged'] = False
notifyJson['repliesNotifyChanged'] = False
if not inboxJson:
return
if not inboxJson.get('orderedItems'):
return
2021-03-23 10:03:45 +00:00
DMdone = False
replyDone = False
2021-12-25 22:09:19 +00:00
for post_json_object in inboxJson['orderedItems']:
if not post_json_object.get('id'):
continue
2021-12-25 22:09:19 +00:00
if not post_json_object.get('type'):
2021-03-23 19:14:49 +00:00
continue
2021-12-25 22:09:19 +00:00
if post_json_object['type'] == 'Announce':
2021-03-23 19:14:49 +00:00
continue
2021-12-29 21:55:09 +00:00
if not _post_is_to_you(actor, post_json_object):
continue
2021-12-26 20:12:18 +00:00
if is_dm(post_json_object):
2021-03-23 10:03:45 +00:00
if not DMdone:
2021-12-29 21:55:09 +00:00
if not _has_read_post(actor, post_json_object['id'], 'dm'):
2021-03-23 10:03:45 +00:00
changed = False
if not notifyJson.get('dmPostId'):
changed = True
else:
2021-12-25 22:09:19 +00:00
if notifyJson['dmPostId'] != post_json_object['id']:
2021-03-23 10:03:45 +00:00
changed = True
if changed:
notifyJson['dmNotify'] = True
notifyJson['dmNotifyChanged'] = True
2021-12-25 22:09:19 +00:00
notifyJson['dmPostId'] = post_json_object['id']
2021-03-23 22:52:00 +00:00
DMdone = True
else:
2021-03-23 10:03:45 +00:00
if not replyDone:
2021-12-29 21:55:09 +00:00
if not _has_read_post(actor, post_json_object['id'],
'replies'):
2021-03-23 10:03:45 +00:00
changed = False
if not notifyJson.get('repliesPostId'):
changed = True
else:
2021-12-25 22:09:19 +00:00
if notifyJson['repliesPostId'] != \
post_json_object['id']:
2021-03-23 10:03:45 +00:00
changed = True
if changed:
notifyJson['repliesNotify'] = True
notifyJson['repliesNotifyChanged'] = True
2021-12-25 22:09:19 +00:00
notifyJson['repliesPostId'] = post_json_object['id']
2021-03-23 22:52:00 +00:00
replyDone = True
2021-12-29 21:55:09 +00:00
def _desktop_clear_screen() -> None:
2021-03-15 14:30:59 +00:00
"""Clears the screen
"""
2021-03-15 13:35:12 +00:00
os.system('cls' if os.name == 'nt' else 'clear')
2021-03-15 13:32:15 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_show_banner() -> None:
2021-03-15 14:30:59 +00:00
"""Shows the banner at the top
"""
2021-03-15 14:36:03 +00:00
bannerFilename = 'banner.txt'
2021-03-15 14:31:33 +00:00
if not os.path.isfile(bannerFilename):
2021-03-15 14:36:03 +00:00
bannerTheme = 'starlight'
bannerFilename = 'theme/' + bannerTheme + '/banner.txt'
if not os.path.isfile(bannerFilename):
return
with open(bannerFilename, 'r') as bannerFile:
banner = bannerFile.read()
if banner:
print(banner + '\n')
2021-03-15 14:30:59 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_wait_for_cmd(timeout: int, debug: bool) -> str:
2021-03-17 10:04:49 +00:00
"""Waits for a command to be entered with a timeout
Returns the command, or None on timeout
2021-03-04 14:36:24 +00:00
"""
2021-03-04 15:21:38 +00:00
i, o, e = select.select([sys.stdin], [], [], timeout)
if (i):
2021-03-04 15:27:27 +00:00
text = sys.stdin.readline().strip()
2021-03-04 15:21:38 +00:00
if debug:
2021-03-04 15:27:27 +00:00
print("Text entered: " + text)
return text
2021-03-04 15:21:38 +00:00
else:
2021-03-04 14:36:24 +00:00
if debug:
2021-03-04 15:21:38 +00:00
print("Timeout")
2021-03-04 14:36:24 +00:00
return None
2021-03-04 13:57:30 +00:00
2021-12-29 21:55:09 +00:00
def _speaker_espeak(espeak, pitch: int, rate: int, srange: int,
sayText: str) -> None:
2021-03-04 14:54:30 +00:00
"""Speaks the given text with espeak
"""
espeak.set_parameter(espeak.Parameter.Pitch, pitch)
espeak.set_parameter(espeak.Parameter.Rate, rate)
espeak.set_parameter(espeak.Parameter.Range, srange)
espeak.synth(html.unescape(sayText))
2021-12-29 21:55:09 +00:00
def _speaker_picospeaker(pitch: int, rate: int, system_language: str,
sayText: str) -> None:
2021-03-16 10:37:51 +00:00
"""TTS using picospeaker
"""
2021-03-04 14:54:30 +00:00
speakerLang = 'en-GB'
2021-12-13 15:49:28 +00:00
supportedLanguages = {
"fr": "fr-FR",
"es": "es-ES",
"de": "de-DE",
"it": "it-IT"
}
for lang, speakerStr in supportedLanguages.items():
2021-12-25 23:03:28 +00:00
if system_language.startswith(lang):
2021-12-13 15:49:28 +00:00
speakerLang = speakerStr
break
2021-03-25 14:15:36 +00:00
sayText = str(sayText).replace('"', "'")
2021-03-04 14:54:30 +00:00
speakerCmd = 'picospeaker ' + \
'-l ' + speakerLang + \
' -r ' + str(rate) + \
' -p ' + str(pitch) + ' "' + \
2021-03-25 13:57:47 +00:00
html.unescape(str(sayText)) + '" 2> /dev/null'
2021-03-04 14:54:30 +00:00
os.system(speakerCmd)
2021-12-29 21:55:09 +00:00
def _play_notification_sound(soundFilename: str,
player: str = 'ffplay') -> None:
2021-03-09 19:52:10 +00:00
"""Plays a sound
"""
if not os.path.isfile(soundFilename):
return
if player == 'ffplay':
os.system('ffplay ' + soundFilename +
2021-03-10 15:43:21 +00:00
' -autoexit -hide_banner -nodisp 2> /dev/null')
2021-03-09 19:52:10 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_notification(notificationType: str,
title: str, message: str) -> None:
2021-03-09 20:32:50 +00:00
"""Shows a desktop notification
"""
if not notificationType:
return
if notificationType == 'notify-send':
# Ubuntu
os.system('notify-send "' + title + '" "' + message + '"')
2021-03-11 10:01:05 +00:00
elif notificationType == 'zenity':
# Zenity
os.system('zenity --notification --title "' + title +
'" --text="' + message + '"')
2021-03-09 20:32:50 +00:00
elif notificationType == 'osascript':
# Mac
os.system("osascript -e 'display notification \"" +
message + "\" with title \"" + title + "\"'")
elif notificationType == 'New-BurntToastNotification':
# Windows
os.system("New-BurntToastNotification -Text \"" +
title + "\", '" + message + "'")
2021-12-29 21:55:09 +00:00
def _text_to_speech(sayStr: str, screenreader: str,
pitch: int, rate: int, srange: int,
system_language: str, espeak=None) -> None:
2021-03-10 12:11:42 +00:00
"""Say something via TTS
"""
# speak the post content
if screenreader == 'espeak':
2021-12-29 21:55:09 +00:00
_speaker_espeak(espeak, pitch, rate, srange, sayStr)
2021-03-10 12:11:42 +00:00
elif screenreader == 'picospeaker':
2021-12-29 21:55:09 +00:00
_speaker_picospeaker(pitch, rate, system_language, sayStr)
2021-03-10 12:11:42 +00:00
2021-12-29 21:55:09 +00:00
def _say_command(content: str, sayStr: str, screenreader: str,
system_language: str,
espeak=None,
speakerName: str = 'screen reader',
speakerGender: str = 'They/Them') -> None:
2021-03-10 10:25:41 +00:00
"""Speaks a command
"""
print(content)
2021-03-10 10:32:08 +00:00
if not screenreader:
return
2021-03-10 10:25:41 +00:00
2021-12-29 21:55:09 +00:00
pitch = get_speaker_pitch(speakerName,
screenreader, speakerGender)
rate = get_speaker_rate(speakerName, screenreader)
srange = get_speaker_range(speakerName)
_text_to_speech(sayStr, screenreader,
pitch, rate, srange,
system_language, espeak)
def _desktop_reply_to_post(session, post_id: str,
base_dir: str, nickname: str, password: str,
domain: str, port: int, http_prefix: str,
cached_webfingers: {}, person_cache: {},
debug: bool, subject: str,
screenreader: str, system_language: str,
espeak, conversationId: str,
low_bandwidth: bool,
content_license_url: str,
signing_priv_key_pem: str) -> None:
2021-03-17 10:04:49 +00:00
"""Use the desktop client to send a reply to the most recent post
2021-03-10 18:30:00 +00:00
"""
2021-12-26 19:47:06 +00:00
if '://' not in post_id:
2021-03-10 18:30:00 +00:00
return
2021-12-27 22:19:18 +00:00
toNickname = get_nickname_from_actor(post_id)
2021-12-27 19:05:25 +00:00
toDomain, toPort = get_domain_from_actor(post_id)
2021-03-10 18:30:00 +00:00
sayStr = 'Replying to ' + toNickname + '@' + toDomain
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
sayStr = 'Type your reply message, then press Enter.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
replyMessage = input()
if not replyMessage:
sayStr = 'No reply was entered.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
return
replyMessage = replyMessage.strip()
if not replyMessage:
sayStr = 'No reply was entered.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
return
print('')
2021-03-10 18:30:00 +00:00
sayStr = 'You entered this reply:'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
_say_command(replyMessage, replyMessage, screenreader,
system_language, espeak)
2021-03-10 18:30:00 +00:00
sayStr = 'Send this reply, yes or no?'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
yesno = input()
if 'y' not in yesno.lower():
sayStr = 'Abandoning reply'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
return
ccUrl = None
followersOnly = False
attach = None
mediaType = None
attachedImageDescription = None
isArticle = False
subject = None
commentsEnabled = True
2021-05-09 19:29:53 +00:00
city = 'London, England'
sayStr = 'Sending reply'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
if send_post_via_server(signing_priv_key_pem, __version__,
base_dir, session, nickname, password,
domain, port,
toNickname, toDomain, toPort, ccUrl,
http_prefix, replyMessage, followersOnly,
commentsEnabled, attach, mediaType,
attachedImageDescription, city,
cached_webfingers, person_cache, isArticle,
system_language, low_bandwidth,
content_license_url,
debug, post_id, post_id,
conversationId, subject) == 0:
2021-03-10 19:31:33 +00:00
sayStr = 'Reply sent'
else:
sayStr = 'Reply failed'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_new_post(session,
base_dir: str, nickname: str, password: str,
domain: str, port: int, http_prefix: str,
cached_webfingers: {}, person_cache: {},
debug: bool,
screenreader: str, system_language: str,
espeak, low_bandwidth: bool,
content_license_url: str,
signing_priv_key_pem: str) -> None:
2021-03-17 10:04:49 +00:00
"""Use the desktop client to create a new post
"""
2021-08-08 16:52:32 +00:00
conversationId = None
sayStr = 'Create new post'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
sayStr = 'Type your post, then press Enter.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
newMessage = input()
if not newMessage:
sayStr = 'No post was entered.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
return
newMessage = newMessage.strip()
if not newMessage:
sayStr = 'No post was entered.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
return
2021-03-21 13:43:04 +00:00
print('')
sayStr = 'You entered this public post:'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
_say_command(newMessage, newMessage, screenreader, system_language, espeak)
sayStr = 'Send this post, yes or no?'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
yesno = input()
if 'y' not in yesno.lower():
sayStr = 'Abandoning new post'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
return
ccUrl = None
followersOnly = False
attach = None
mediaType = None
attachedImageDescription = None
2021-05-09 19:29:53 +00:00
city = 'London, England'
isArticle = False
subject = None
commentsEnabled = True
subject = None
sayStr = 'Sending'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
if send_post_via_server(signing_priv_key_pem, __version__,
base_dir, session, nickname, password,
domain, port,
None, '#Public', port, ccUrl,
http_prefix, newMessage, followersOnly,
commentsEnabled, attach, mediaType,
attachedImageDescription, city,
cached_webfingers, person_cache, isArticle,
system_language, low_bandwidth,
content_license_url,
debug, None, None,
conversationId, subject) == 0:
sayStr = 'Post sent'
else:
sayStr = 'Post failed'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-12-29 21:55:09 +00:00
def _safe_message(content: str) -> str:
"""Removes anything potentially unsafe from a string
"""
return content.replace('`', '').replace('$(', '$ (')
2021-12-29 21:55:09 +00:00
def _timeline_is_empty(boxJson: {}) -> bool:
"""Returns true if the given timeline is empty
"""
empty = False
if not boxJson:
empty = True
else:
if not isinstance(boxJson, dict):
empty = True
elif not boxJson.get('orderedItems'):
empty = True
return empty
2021-12-29 21:55:09 +00:00
def _get_first_item_id(boxJson: {}) -> str:
"""Returns the id of the first item in the timeline
"""
2021-12-29 21:55:09 +00:00
if _timeline_is_empty(boxJson):
return
if len(boxJson['orderedItems']) == 0:
return
return boxJson['orderedItems'][0]['id']
2021-12-29 21:55:09 +00:00
def _text_only_content(content: str) -> str:
"""Remove formatting from the given string
"""
content = urllib.parse.unquote_plus(content)
content = html.unescape(content)
2021-12-27 15:43:22 +00:00
return remove_html(content)
2021-12-29 21:55:09 +00:00
def _get_image_description(post_json_object: {}) -> str:
2021-03-19 14:49:40 +00:00
"""Returns a image description/s on a post
"""
imageDescription = ''
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('attachment'):
2021-03-19 14:49:40 +00:00
return imageDescription
2021-12-25 22:09:19 +00:00
attachList = post_json_object['object']['attachment']
2021-03-19 14:49:40 +00:00
if not isinstance(attachList, list):
return imageDescription
# for each attachment
for img in attachList:
if not isinstance(img, dict):
continue
if not img.get('name'):
continue
if not isinstance(img['name'], str):
continue
messageStr = img['name']
if messageStr:
messageStr = messageStr.strip()
if not messageStr.endswith('.'):
imageDescription += messageStr + '. '
else:
imageDescription += messageStr + ' '
return imageDescription
2021-12-29 21:55:09 +00:00
def _show_likes_on_post(post_json_object: {}, maxLikes: int) -> None:
2021-03-23 14:36:35 +00:00
"""Shows the likes on a post
"""
2021-12-26 10:57:03 +00:00
if not has_object_dict(post_json_object):
2021-03-23 14:36:35 +00:00
return
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('likes'):
2021-03-23 14:36:35 +00:00
return
2021-12-25 22:09:19 +00:00
objectLikes = post_json_object['object']['likes']
2021-12-13 16:04:12 +00:00
if not isinstance(objectLikes, dict):
2021-03-23 14:36:35 +00:00
return
2021-12-13 16:04:12 +00:00
if not objectLikes.get('items'):
2021-03-23 14:36:35 +00:00
return
2021-12-13 16:04:12 +00:00
if not isinstance(objectLikes['items'], list):
2021-03-23 14:50:40 +00:00
return
2021-03-23 14:36:35 +00:00
print('')
ctr = 0
2021-12-13 16:04:12 +00:00
for item in objectLikes['items']:
2021-03-23 14:36:35 +00:00
print('' + str(item['actor']))
ctr += 1
if ctr >= maxLikes:
break
2021-12-29 21:55:09 +00:00
def _show_replies_on_post(post_json_object: {}, max_replies: int) -> None:
2021-03-23 19:14:49 +00:00
"""Shows the replies on a post
"""
2021-12-26 10:57:03 +00:00
if not has_object_dict(post_json_object):
2021-03-23 19:14:49 +00:00
return
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('replies'):
2021-03-23 19:14:49 +00:00
return
2021-12-25 22:09:19 +00:00
objectReplies = post_json_object['object']['replies']
2021-12-13 16:04:12 +00:00
if not isinstance(objectReplies, dict):
2021-03-23 19:14:49 +00:00
return
2021-12-13 16:04:12 +00:00
if not objectReplies.get('items'):
2021-03-23 19:14:49 +00:00
return
2021-12-13 16:04:12 +00:00
if not isinstance(objectReplies['items'], list):
2021-03-23 19:14:49 +00:00
return
print('')
ctr = 0
2021-12-13 16:04:12 +00:00
for item in objectReplies['items']:
2021-03-23 19:14:49 +00:00
print('' + str(item['url']))
ctr += 1
2021-12-25 21:11:35 +00:00
if ctr >= max_replies:
2021-03-23 19:14:49 +00:00
break
2021-12-29 21:55:09 +00:00
def _read_local_box_post(session, nickname: str, domain: str,
http_prefix: str, base_dir: str, boxName: str,
pageNumber: int, index: int, boxJson: {},
system_language: str,
screenreader: str, espeak,
translate: {}, yourActor: str,
domain_full: str, person_cache: {},
signing_priv_key_pem: str,
blockedCache: {}) -> {}:
2021-03-15 15:14:54 +00:00
"""Reads a post from the given timeline
2021-03-22 18:27:48 +00:00
Returns the post json
2021-03-15 15:14:54 +00:00
"""
2021-12-29 21:55:09 +00:00
if _timeline_is_empty(boxJson):
return {}
2021-03-12 19:55:16 +00:00
2021-12-29 21:55:09 +00:00
post_json_object = _desktop_get_box_post_object(boxJson, index)
2021-12-25 22:09:19 +00:00
if not post_json_object:
return {}
2021-03-12 19:55:16 +00:00
gender = 'They/Them'
2021-03-19 17:23:30 +00:00
boxNameStr = boxName
if boxName.startswith('tl'):
boxNameStr = boxName[2:]
sayStr = 'Reading ' + boxNameStr + ' post ' + str(index) + \
' from page ' + str(pageNumber) + '.'
2021-03-16 18:08:18 +00:00
sayStr2 = sayStr.replace(' dm ', ' DM ')
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr2, screenreader, system_language, espeak)
2021-03-23 11:22:09 +00:00
print('')
2021-03-12 20:51:04 +00:00
2021-12-25 22:09:19 +00:00
if post_json_object['type'] == 'Announce':
actor = post_json_object['actor']
2021-12-27 22:19:18 +00:00
nameStr = get_nickname_from_actor(actor)
2021-12-26 20:01:37 +00:00
recent_posts_cache = {}
2021-12-25 18:54:50 +00:00
allow_local_network_access = False
2021-12-25 17:15:52 +00:00
yt_replace_domain = None
2021-12-25 20:55:47 +00:00
twitter_replacement_domain = None
2021-12-25 22:09:19 +00:00
post_json_object2 = \
2021-12-29 21:55:09 +00:00
download_announce(session, base_dir,
http_prefix,
nickname, domain,
post_json_object,
__version__, translate,
yt_replace_domain,
twitter_replacement_domain,
allow_local_network_access,
recent_posts_cache, False,
system_language,
domain_full, person_cache,
signing_priv_key_pem,
blockedCache)
2021-12-25 22:09:19 +00:00
if post_json_object2:
2021-12-26 10:57:03 +00:00
if has_object_dict(post_json_object2):
2021-12-25 22:09:19 +00:00
if post_json_object2['object'].get('attributedTo') and \
post_json_object2['object'].get('content'):
attributedTo = post_json_object2['object']['attributedTo']
content = \
2021-12-26 11:29:40 +00:00
get_base_content_from_post(post_json_object2,
system_language)
if isinstance(attributedTo, str) and content:
2021-07-09 20:00:02 +00:00
actor = attributedTo
nameStr += ' ' + translate['announces'] + ' ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(actor)
2021-07-09 20:00:02 +00:00
sayStr = nameStr
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-07-09 20:00:02 +00:00
print('')
if screenreader:
time.sleep(2)
content = \
2021-12-29 21:55:09 +00:00
_text_only_content(content)
content += _get_image_description(post_json_object2)
2021-07-09 20:00:02 +00:00
messageStr, detectedLinks = \
2021-12-29 21:55:09 +00:00
speakable_text(base_dir, content, translate)
2021-07-09 20:00:02 +00:00
sayStr = content
2021-12-29 21:55:09 +00:00
_say_command(sayStr, messageStr, screenreader,
system_language, espeak)
2021-12-25 22:09:19 +00:00
return post_json_object2
return {}
2021-12-25 22:09:19 +00:00
attributedTo = post_json_object['object']['attributedTo']
2021-07-09 20:00:02 +00:00
if not attributedTo:
return {}
2021-12-26 11:29:40 +00:00
content = get_base_content_from_post(post_json_object, system_language)
2021-07-09 20:00:02 +00:00
if not isinstance(attributedTo, str) or \
not isinstance(content, str):
return {}
actor = attributedTo
2021-12-27 22:19:18 +00:00
nameStr = get_nickname_from_actor(actor)
2021-12-29 21:55:09 +00:00
content = _text_only_content(content)
content += _get_image_description(post_json_object)
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
2021-03-16 11:56:24 +00:00
sayStr = 'Encrypted message. Please enter your passphrase.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
content = pgp_decrypt(domain, content, actor, signing_priv_key_pem)
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
2021-03-16 11:56:24 +00:00
sayStr = 'Message could not be decrypted'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
return {}
2021-03-16 11:56:24 +00:00
2021-12-29 21:55:09 +00:00
content = _safe_message(content)
messageStr, detectedLinks = speakable_text(base_dir, content, translate)
if screenreader:
time.sleep(2)
2021-03-12 20:51:04 +00:00
2021-03-12 19:55:16 +00:00
# say the speaker's name
2021-12-29 21:55:09 +00:00
_say_command(nameStr, nameStr, screenreader,
system_language, espeak, nameStr, gender)
2021-03-23 11:22:09 +00:00
print('')
2021-03-12 19:55:16 +00:00
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('inReplyTo'):
print('Replying to ' + post_json_object['object']['inReplyTo'] + '\n')
2021-03-19 17:23:30 +00:00
if screenreader:
time.sleep(2)
2021-03-12 19:55:16 +00:00
# speak the post content
2021-12-29 21:55:09 +00:00
_say_command(content, messageStr, screenreader,
system_language, espeak, nameStr, gender)
2021-12-29 21:55:09 +00:00
_show_likes_on_post(post_json_object, 10)
_show_replies_on_post(post_json_object, 10)
2021-03-23 14:16:44 +00:00
# if the post is addressed to you then mark it as read
2021-12-29 21:55:09 +00:00
if _post_is_to_you(yourActor, post_json_object):
2021-12-26 20:12:18 +00:00
if is_dm(post_json_object):
2021-12-29 21:55:09 +00:00
_mark_post_as_read(yourActor, post_json_object['id'], 'dm')
else:
2021-12-29 21:55:09 +00:00
_mark_post_as_read(yourActor, post_json_object['id'], 'replies')
2021-12-25 22:09:19 +00:00
return post_json_object
2021-03-12 19:55:16 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_show_actor(base_dir: str, actor_json: {}, translate: {},
system_language: str, screenreader: str,
espeak) -> None:
2021-03-25 12:43:11 +00:00
"""Shows information for the given actor
2021-03-25 12:39:10 +00:00
"""
2021-12-26 10:29:52 +00:00
actor = actor_json['id']
2021-12-27 22:19:18 +00:00
actorNickname = get_nickname_from_actor(actor)
2021-12-27 19:05:25 +00:00
actorDomain, actorPort = get_domain_from_actor(actor)
2021-12-26 12:45:03 +00:00
actorDomainFull = get_full_domain(actorDomain, actorPort)
2021-03-25 12:39:10 +00:00
handle = '@' + actorNickname + '@' + actorDomainFull
2021-03-25 14:51:41 +00:00
sayStr = 'Profile for ' + html.unescape(handle)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-25 12:39:10 +00:00
print(actor)
2021-12-26 10:29:52 +00:00
if actor_json.get('movedTo'):
sayStr = 'Moved to ' + html.unescape(actor_json['movedTo'])
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-12-26 10:29:52 +00:00
if actor_json.get('alsoKnownAs'):
2021-03-25 12:39:10 +00:00
alsoKnownAsStr = ''
ctr = 0
2021-12-26 10:29:52 +00:00
for altActor in actor_json['alsoKnownAs']:
2021-03-25 12:39:10 +00:00
if ctr > 0:
alsoKnownAsStr += ', '
ctr += 1
alsoKnownAsStr += altActor
2021-03-25 13:57:47 +00:00
sayStr = 'Also known as ' + html.unescape(alsoKnownAsStr)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-12-26 10:29:52 +00:00
if actor_json.get('summary'):
2021-12-27 15:43:22 +00:00
sayStr = html.unescape(remove_html(actor_json['summary']))
2021-03-25 13:57:47 +00:00
sayStr = sayStr.replace('"', "'")
2021-12-29 21:55:09 +00:00
sayStr2 = speakable_text(base_dir, sayStr, translate)[0]
_say_command(sayStr, sayStr2, screenreader, system_language, espeak)
def _desktop_show_profile(session, nickname: str, domain: str,
http_prefix: str, base_dir: str, boxName: str,
pageNumber: int, index: int, boxJson: {},
system_language: str,
screenreader: str, espeak,
translate: {}, yourActor: str,
post_json_object: {},
signing_priv_key_pem: str) -> {}:
2021-03-22 18:27:48 +00:00
"""Shows the profile of the actor for the given post
Returns the actor json
"""
2021-12-29 21:55:09 +00:00
if _timeline_is_empty(boxJson):
2021-03-22 18:27:48 +00:00
return {}
2021-12-25 22:09:19 +00:00
if not post_json_object:
2021-12-29 21:55:09 +00:00
post_json_object = _desktop_get_box_post_object(boxJson, index)
2021-12-25 22:09:19 +00:00
if not post_json_object:
2021-03-23 16:17:03 +00:00
return {}
2021-03-22 18:27:48 +00:00
actor = None
2021-12-25 22:09:19 +00:00
if post_json_object['type'] == 'Announce':
2021-12-27 22:19:18 +00:00
nickname = get_nickname_from_actor(post_json_object['object'])
2021-03-22 18:27:48 +00:00
if nickname:
nickStr = '/' + nickname + '/'
2021-12-25 22:09:19 +00:00
if nickStr in post_json_object['object']:
2021-03-22 18:27:48 +00:00
actor = \
2021-12-25 22:09:19 +00:00
post_json_object['object'].split(nickStr)[0] + \
2021-03-22 18:27:48 +00:00
'/' + nickname
else:
2021-12-25 22:09:19 +00:00
actor = post_json_object['object']['attributedTo']
2021-03-22 18:27:48 +00:00
if not actor:
return {}
isHttp = False
if 'http://' in actor:
isHttp = True
2021-12-26 10:29:52 +00:00
actor_json, asHeader = \
2021-12-29 21:55:09 +00:00
get_actor_json(domain, actor, isHttp, False, False, True,
signing_priv_key_pem, session)
2021-03-22 18:27:48 +00:00
2021-12-29 21:55:09 +00:00
_desktop_show_actor(base_dir, actor_json, translate,
system_language, screenreader, espeak)
2021-03-22 18:27:48 +00:00
2021-12-26 10:29:52 +00:00
return actor_json
2021-03-22 18:27:48 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_show_profile_from_handle(session, nickname: str, domain: str,
http_prefix: str, base_dir: str,
boxName: str, handle: str,
system_language: str,
screenreader: str, espeak,
translate: {}, yourActor: str,
post_json_object: {},
signing_priv_key_pem: str) -> {}:
2021-03-25 12:57:01 +00:00
"""Shows the profile for a handle
Returns the actor json
"""
2021-12-26 10:29:52 +00:00
actor_json, asHeader = \
2021-12-29 21:55:09 +00:00
get_actor_json(domain, handle, False, False, False, True,
signing_priv_key_pem, session)
2021-03-25 12:57:01 +00:00
2021-12-29 21:55:09 +00:00
_desktop_show_actor(base_dir, actor_json, translate,
system_language, screenreader, espeak)
2021-03-25 12:57:01 +00:00
2021-12-26 10:29:52 +00:00
return actor_json
2021-03-25 12:57:01 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_get_box_post_object(boxJson: {}, index: int) -> {}:
"""Gets the post with the given index from the timeline
"""
ctr = 0
2021-12-25 22:09:19 +00:00
for post_json_object in boxJson['orderedItems']:
if not post_json_object.get('type'):
continue
2021-12-25 22:09:19 +00:00
if not post_json_object.get('object'):
continue
2021-12-25 22:09:19 +00:00
if post_json_object['type'] == 'Announce':
if not isinstance(post_json_object['object'], str):
continue
ctr += 1
if ctr == index:
2021-12-25 22:09:19 +00:00
return post_json_object
continue
2021-12-26 10:57:03 +00:00
if not has_object_dict(post_json_object):
continue
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('published'):
continue
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('content'):
continue
ctr += 1
if ctr == index:
2021-12-25 22:09:19 +00:00
return post_json_object
return None
2021-12-29 21:55:09 +00:00
def _format_published(published: str) -> str:
2021-03-18 22:16:01 +00:00
"""Formats the published time for display on timeline
"""
dateStr = published.split('T')[0]
monthStr = dateStr.split('-')[1]
dayStr = dateStr.split('-')[2]
timeStr = published.split('T')[1]
hourStr = timeStr.split(':')[0]
minStr = timeStr.split(':')[1]
return monthStr + '-' + dayStr + ' ' + hourStr + ':' + minStr + 'Z'
2021-12-29 21:55:09 +00:00
def _pad_to_width(content: str, width: int) -> str:
"""Pads the given string to the given width
"""
if len(content) > width:
content = content[:width]
else:
while len(content) < width:
content += ' '
return content
2021-12-29 21:55:09 +00:00
def _highlight_text(text: str) -> str:
2021-03-23 23:33:33 +00:00
"""Returns a highlighted version of the given text
"""
return '\33[7m' + text + '\33[0m'
2021-12-29 21:55:09 +00:00
def _desktop_show_box(indent: str,
followRequestsJson: {},
yourActor: str, boxName: str, boxJson: {},
translate: {},
screenreader: str, system_language: str, espeak,
pageNumber: int,
newReplies: bool,
newDMs: bool) -> bool:
"""Shows online timeline
"""
numberWidth = 2
nameWidth = 16
contentWidth = 50
# title
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
notificationIcons = ''
2021-03-19 17:23:30 +00:00
if boxName.startswith('tl'):
2021-03-19 16:10:14 +00:00
boxNameStr = boxName[2:]
2021-03-19 15:39:16 +00:00
else:
2021-03-19 16:10:14 +00:00
boxNameStr = boxName
2021-12-29 21:55:09 +00:00
titleStr = _highlight_text(boxNameStr.upper())
2021-03-24 17:24:22 +00:00
# if newDMs:
# notificationIcons += ' 📩'
# if newReplies:
# notificationIcons += ' 📨'
2021-03-22 16:56:13 +00:00
if notificationIcons:
while len(titleStr) < 95 - len(notificationIcons):
titleStr += ' '
titleStr += notificationIcons
print(indent + titleStr + '\n')
2021-12-29 21:55:09 +00:00
if _timeline_is_empty(boxJson):
2021-03-19 16:10:14 +00:00
boxStr = boxNameStr
if boxName == 'dm':
boxStr = 'DM'
sayStr = indent + 'You have no ' + boxStr + ' posts yet.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
print('')
return False
ctr = 1
2021-12-25 22:09:19 +00:00
for post_json_object in boxJson['orderedItems']:
if not post_json_object.get('type'):
continue
2021-12-25 22:09:19 +00:00
if post_json_object['type'] == 'Announce':
if post_json_object.get('actor') and \
post_json_object.get('object'):
if isinstance(post_json_object['object'], str):
authorActor = post_json_object['actor']
2021-12-27 22:19:18 +00:00
name = get_nickname_from_actor(authorActor) + ''
2021-12-29 21:55:09 +00:00
name = _pad_to_width(name, nameWidth)
ctrStr = str(ctr)
2021-12-29 21:55:09 +00:00
posStr = _pad_to_width(ctrStr, numberWidth)
published = \
_format_published(post_json_object['published'])
announcedNickname = \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(post_json_object['object'])
announcedDomain, announcedPort = \
2021-12-27 19:05:25 +00:00
get_domain_from_actor(post_json_object['object'])
announcedHandle = announcedNickname + '@' + announcedDomain
2021-03-23 11:22:09 +00:00
lineStr = \
indent + str(posStr) + ' | ' + name + ' | ' + \
published + ' | ' + \
2021-12-29 21:55:09 +00:00
_pad_to_width(announcedHandle, contentWidth)
2021-03-23 11:22:09 +00:00
print(lineStr)
ctr += 1
continue
2021-12-26 10:57:03 +00:00
if not has_object_dict(post_json_object):
continue
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('published'):
continue
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('content'):
continue
ctrStr = str(ctr)
2021-12-29 21:55:09 +00:00
posStr = _pad_to_width(ctrStr, numberWidth)
2021-12-25 22:09:19 +00:00
authorActor = post_json_object['object']['attributedTo']
contentWarning = None
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('summary'):
contentWarning = '' + \
2021-12-29 21:55:09 +00:00
_pad_to_width(post_json_object['object']['summary'],
contentWidth)
2021-12-27 22:19:18 +00:00
name = get_nickname_from_actor(authorActor)
# append icons to the end of the name
2021-03-18 20:11:28 +00:00
spaceAdded = False
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('inReplyTo'):
2021-03-18 20:11:28 +00:00
if not spaceAdded:
spaceAdded = True
name += ' '
name += ''
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('replies'):
repliesList = post_json_object['object']['replies']
2021-03-23 19:14:49 +00:00
if repliesList.get('items'):
items = repliesList['items']
for i in range(int(items)):
name += ''
if i > 10:
break
2021-12-29 21:55:09 +00:00
likesCount = no_of_likes(post_json_object)
2021-03-18 20:04:49 +00:00
if likesCount > 10:
likesCount = 10
for like in range(likesCount):
2021-03-18 20:11:28 +00:00
if not spaceAdded:
spaceAdded = True
name += ' '
2021-03-18 20:04:49 +00:00
name += ''
2021-12-29 21:55:09 +00:00
name = _pad_to_width(name, nameWidth)
2021-12-29 21:55:09 +00:00
published = _format_published(post_json_object['published'])
2021-12-26 11:29:40 +00:00
contentStr = get_base_content_from_post(post_json_object,
system_language)
2021-12-29 21:55:09 +00:00
content = _text_only_content(contentStr)
if boxName != 'dm':
2021-12-26 20:12:18 +00:00
if is_dm(post_json_object):
content = '📧' + content
if not contentWarning:
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
content = '🔒' + content
elif '://' in content:
content = '🔗' + content
2021-12-29 21:55:09 +00:00
content = _pad_to_width(content, contentWidth)
else:
# display content warning
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
content = '🔒' + contentWarning
else:
if '://' in content:
content = '🔗' + contentWarning
else:
content = contentWarning
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('ignores'):
2021-03-21 12:15:10 +00:00
content = '🔇'
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('bookmarks'):
2021-03-21 16:09:18 +00:00
content = '🔖' + content
if '\n' in content:
content = content.replace('\n', ' ')
2021-03-23 11:22:09 +00:00
lineStr = indent + str(posStr) + ' | ' + name + ' | ' + \
published + ' | ' + content
if boxName == 'inbox' and \
2021-12-29 21:55:09 +00:00
_post_is_to_you(yourActor, post_json_object):
if not _has_read_post(yourActor, post_json_object['id'], 'dm'):
if not _has_read_post(yourActor, post_json_object['id'],
'replies'):
lineStr = _highlight_text(lineStr)
2021-03-23 11:22:09 +00:00
print(lineStr)
ctr += 1
if followRequestsJson:
2021-12-29 21:55:09 +00:00
_desktop_show_follow_requests(followRequestsJson, translate)
print('')
# say the post number range
2021-03-19 16:10:14 +00:00
sayStr = indent + boxNameStr + ' page ' + str(pageNumber) + \
' containing ' + str(ctr - 1) + ' posts. '
sayStr2 = sayStr.replace('\33[3m', '').replace('\33[0m', '')
sayStr2 = sayStr2.replace('show dm', 'show DM')
sayStr2 = sayStr2.replace('dm post', 'Direct message post')
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr2, screenreader, system_language, espeak)
print('')
return True
2021-12-29 21:55:09 +00:00
def _desktop_new_dm(session, toHandle: str,
base_dir: str, nickname: str, password: str,
domain: str, port: int, http_prefix: str,
cached_webfingers: {}, person_cache: {},
debug: bool,
screenreader: str, system_language: str,
espeak, low_bandwidth: bool,
content_license_url: str,
signing_priv_key_pem: str) -> None:
2021-03-17 10:04:49 +00:00
"""Use the desktop client to create a new direct message
2021-03-14 10:28:48 +00:00
which can include multiple destination handles
"""
if ' ' in toHandle:
handlesList = toHandle.split(' ')
elif ',' in toHandle:
handlesList = toHandle.split(',')
elif ';' in toHandle:
handlesList = toHandle.split(';')
else:
handlesList = [toHandle]
for handle in handlesList:
handle = handle.strip()
2021-12-29 21:55:09 +00:00
_desktop_new_d_mbase(session, handle,
base_dir, nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug,
screenreader, system_language,
espeak, low_bandwidth,
content_license_url,
signing_priv_key_pem)
def _desktop_new_d_mbase(session, toHandle: str,
base_dir: str, nickname: str, password: str,
domain: str, port: int, http_prefix: str,
cached_webfingers: {}, person_cache: {},
debug: bool,
screenreader: str, system_language: str,
espeak, low_bandwidth: bool,
content_license_url: str,
signing_priv_key_pem: str) -> None:
2021-03-17 10:04:49 +00:00
"""Use the desktop client to create a new direct message
2021-03-11 12:24:20 +00:00
"""
2021-08-08 16:52:32 +00:00
conversationId = None
2021-03-11 12:24:20 +00:00
toPort = port
if '://' in toHandle:
2021-12-27 22:19:18 +00:00
toNickname = get_nickname_from_actor(toHandle)
2021-12-27 19:05:25 +00:00
toDomain, toPort = get_domain_from_actor(toHandle)
2021-03-11 12:24:20 +00:00
toHandle = toNickname + '@' + toDomain
else:
if toHandle.startswith('@'):
toHandle = toHandle[1:]
toNickname = toHandle.split('@')[0]
toDomain = toHandle.split('@')[1]
sayStr = 'Create new direct message to ' + toHandle
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
sayStr = 'Type your direct message, then press Enter.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
newMessage = input()
if not newMessage:
sayStr = 'No direct message was entered.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
return
newMessage = newMessage.strip()
if not newMessage:
sayStr = 'No direct message was entered.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
return
sayStr = 'You entered this direct message to ' + toHandle + ':'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
_say_command(newMessage, newMessage, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
ccUrl = None
followersOnly = False
attach = None
mediaType = None
attachedImageDescription = None
2021-05-09 19:29:53 +00:00
city = 'London, England'
2021-03-11 12:24:20 +00:00
isArticle = False
subject = None
commentsEnabled = True
subject = None
# if there is a local PGP key then attempt to encrypt the DM
# using the PGP public key of the recipient
2021-12-29 21:55:09 +00:00
if has_local_pg_pkey():
sayStr = \
'Local PGP key detected...' + \
'Fetching PGP public key for ' + toHandle
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
paddedMessage = newMessage
if len(paddedMessage) < 32:
# add some padding before and after
# This is to guard against cribs based on small messages, like "Hi"
for before in range(randint(1, 16)):
paddedMessage = ' ' + paddedMessage
for after in range(randint(1, 16)):
paddedMessage += ' '
cipherText = \
2021-12-29 21:55:09 +00:00
pgp_encrypt_to_actor(domain, paddedMessage, toHandle,
signing_priv_key_pem)
if not cipherText:
sayStr = \
toHandle + ' has no PGP public key. ' + \
'Your message will be sent in clear text'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
else:
newMessage = cipherText
sayStr = 'Message encrypted'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
sayStr = 'Send this direct message, yes or no?'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
yesno = input()
if 'y' not in yesno.lower():
sayStr = 'Abandoning new direct message'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
return
2021-03-11 12:24:20 +00:00
sayStr = 'Sending'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
if send_post_via_server(signing_priv_key_pem, __version__,
base_dir, session, nickname, password,
domain, port,
toNickname, toDomain, toPort, ccUrl,
http_prefix, newMessage, followersOnly,
commentsEnabled, attach, mediaType,
attachedImageDescription, city,
cached_webfingers, person_cache, isArticle,
system_language, low_bandwidth,
content_license_url,
debug, None, None,
conversationId, subject) == 0:
2021-03-11 12:24:20 +00:00
sayStr = 'Direct message sent'
else:
sayStr = 'Direct message failed'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
2021-12-29 21:55:09 +00:00
def _desktop_show_follow_requests(followRequestsJson: {},
translate: {}) -> None:
"""Shows any follow requests
"""
2021-03-25 10:56:41 +00:00
if not isinstance(followRequestsJson, dict):
return
if not followRequestsJson.get('orderedItems'):
return
if not followRequestsJson['orderedItems']:
return
indent = ' '
print('')
print(indent + 'Follow requests:')
print('')
for item in followRequestsJson['orderedItems']:
2021-12-27 22:19:18 +00:00
handleNickname = get_nickname_from_actor(item)
2021-12-27 19:05:25 +00:00
handleDomain, handlePort = get_domain_from_actor(item)
handleDomainFull = \
2021-12-26 12:45:03 +00:00
get_full_domain(handleDomain, handlePort)
print(indent + ' 👤 ' +
handleNickname + '@' + handleDomainFull)
2021-12-29 21:55:09 +00:00
def _desktop_show_following(followingJson: {}, translate: {},
pageNumber: int, indent: str,
followType='following') -> None:
"""Shows a page of accounts followed
"""
2021-03-25 10:58:53 +00:00
if not isinstance(followingJson, dict):
return
if not followingJson.get('orderedItems'):
return
if not followingJson['orderedItems']:
return
print('')
if followType == 'following':
print(indent + 'Following page ' + str(pageNumber))
elif followType == 'followers':
print(indent + 'Followers page ' + str(pageNumber))
print('')
for item in followingJson['orderedItems']:
2021-12-27 22:19:18 +00:00
handleNickname = get_nickname_from_actor(item)
2021-12-27 19:05:25 +00:00
handleDomain, handlePort = get_domain_from_actor(item)
handleDomainFull = \
2021-12-26 12:45:03 +00:00
get_full_domain(handleDomain, handlePort)
print(indent + ' 👤 ' +
handleNickname + '@' + handleDomainFull)
2021-12-29 21:55:09 +00:00
def run_desktop_client(base_dir: str, proxy_type: str, http_prefix: str,
nickname: str, domain: str, port: int,
password: str, screenreader: str,
system_language: str,
notificationSounds: bool,
notificationType: str,
noKeyPress: bool,
storeInboxPosts: bool,
showNewPosts: bool,
language: str,
debug: bool, low_bandwidth: bool) -> None:
2021-03-17 10:04:49 +00:00
"""Runs the desktop and screen reader client,
which announces new inbox items
2021-03-04 13:57:30 +00:00
"""
# TODO: this should probably be retrieved somehow from the server
2021-12-25 23:03:28 +00:00
signing_priv_key_pem = None
2021-12-25 17:13:38 +00:00
content_license_url = 'https://creativecommons.org/licenses/by/4.0'
2021-11-08 18:09:24 +00:00
blockedCache = {}
2021-03-15 14:30:59 +00:00
indent = ' '
2021-03-15 13:51:21 +00:00
if showNewPosts:
indent = ''
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2021-03-14 10:41:21 +00:00
2021-03-10 10:25:41 +00:00
espeak = None
2021-03-09 19:52:10 +00:00
if screenreader:
if screenreader == 'espeak':
print('Setting up espeak')
from espeak import espeak
elif screenreader != 'picospeaker':
print(screenreader + ' is not a supported TTS system')
return
2021-03-04 13:57:30 +00:00
2021-03-15 13:51:21 +00:00
sayStr = indent + 'Running ' + screenreader + ' for ' + \
nickname + '@' + domain
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-03-09 21:30:23 +00:00
else:
2021-03-15 13:51:21 +00:00
print(indent + 'Running desktop notifications for ' +
nickname + '@' + domain)
if notificationSounds:
2021-03-15 13:51:21 +00:00
sayStr = indent + 'Notification sounds on'
else:
2021-03-15 13:51:21 +00:00
sayStr = indent + 'Notification sounds off'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-12-26 13:17:46 +00:00
curr_timeline = 'inbox'
pageNumber = 1
2021-03-10 10:51:06 +00:00
2021-12-25 22:09:19 +00:00
post_json_object = {}
2021-03-10 10:25:41 +00:00
originalScreenReader = screenreader
2021-03-22 13:43:20 +00:00
soundsDir = 'theme/default/sounds/'
# prevSay = ''
# prevCalendar = False
# prevFollow = False
# prevLike = ''
# prevShare = False
2021-03-22 13:43:20 +00:00
dmSoundFilename = soundsDir + 'dm.ogg'
replySoundFilename = soundsDir + 'reply.ogg'
# calendarSoundFilename = soundsDir + 'calendar.ogg'
# followSoundFilename = soundsDir + 'follow.ogg'
# likeSoundFilename = soundsDir + 'like.ogg'
# shareSoundFilename = soundsDir + 'share.ogg'
player = 'ffplay'
2021-03-10 12:37:44 +00:00
nameStr = None
gender = None
messageStr = None
2021-03-11 10:52:06 +00:00
content = None
2021-12-25 22:28:18 +00:00
cached_webfingers = {}
2021-12-25 22:17:49 +00:00
person_cache = {}
newRepliesExist = False
newDMsExist = False
2021-03-17 20:18:00 +00:00
pgpKeyUpload = False
2021-03-18 17:30:47 +00:00
sayStr = indent + 'Loading translations file'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-12-25 23:03:28 +00:00
translate, system_language = \
2021-12-26 19:12:02 +00:00
load_translations_from_file(base_dir, language)
2021-03-18 17:27:46 +00:00
sayStr = indent + 'Connecting...'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
session = create_session(proxy_type)
2021-03-18 17:30:47 +00:00
sayStr = indent + '/q or /quit to exit'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-12-26 12:45:03 +00:00
domain_full = get_full_domain(domain, port)
2021-12-26 10:19:59 +00:00
yourActor = local_actor_url(http_prefix, nickname, domain_full)
2021-12-26 10:29:52 +00:00
actor_json = None
2021-03-22 13:43:20 +00:00
notifyJson = {
"dmPostId": "Initial",
"dmNotify": False,
"dmNotifyChanged": False,
"repliesPostId": "Initial",
"repliesNotify": False,
"repliesNotifyChanged": False
}
prevTimelineFirstId = ''
2021-04-01 16:30:13 +00:00
desktopShown = False
while (1):
2021-03-17 20:18:00 +00:00
if not pgpKeyUpload:
2021-12-29 21:55:09 +00:00
if not has_local_pg_pkey():
2021-05-05 09:57:29 +00:00
print('No PGP public key was found')
else:
sayStr = indent + 'Uploading PGP public key'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
pgp_public_key_upload(base_dir, session,
nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug, False,
signing_priv_key_pem)
2021-05-05 09:57:29 +00:00
sayStr = indent + 'PGP public key uploaded'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-03-17 20:18:00 +00:00
pgpKeyUpload = True
2021-12-29 21:55:09 +00:00
boxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, pageNumber,
debug, signing_priv_key_pem)
followRequestsJson = \
2021-12-29 21:55:09 +00:00
get_follow_requests_via_server(base_dir, session,
nickname, password,
domain, port,
http_prefix, 1,
cached_webfingers, person_cache,
debug, __version__,
signing_priv_key_pem)
2021-12-26 13:17:46 +00:00
if not (curr_timeline == 'inbox' and pageNumber == 1):
# monitor the inbox to generate notifications
2021-12-29 21:55:09 +00:00
inboxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
'inbox', 1, debug,
signing_priv_key_pem)
else:
inboxJson = boxJson
2021-03-22 16:56:13 +00:00
newDMsExist = False
newRepliesExist = False
if inboxJson:
2021-12-29 21:55:09 +00:00
_new_desktop_notifications(yourActor, inboxJson, notifyJson)
if notifyJson.get('dmNotify'):
2021-03-22 16:56:13 +00:00
newDMsExist = True
2021-03-22 13:43:20 +00:00
if notifyJson.get('dmNotifyChanged'):
2021-12-29 21:55:09 +00:00
_desktop_notification(notificationType,
"Epicyon",
"New DM " + yourActor + '/dm')
2021-03-23 09:43:42 +00:00
if notificationSounds:
2021-12-29 21:55:09 +00:00
_play_notification_sound(dmSoundFilename, player)
if notifyJson.get('repliesNotify'):
2021-03-22 16:56:13 +00:00
newRepliesExist = True
2021-03-22 13:43:20 +00:00
if notifyJson.get('repliesNotifyChanged'):
2021-12-29 21:55:09 +00:00
_desktop_notification(notificationType,
"Epicyon",
"New reply " +
yourActor + '/replies')
2021-03-23 09:43:42 +00:00
if notificationSounds:
2021-12-29 21:55:09 +00:00
_play_notification_sound(replySoundFilename, player)
if boxJson:
2021-12-29 21:55:09 +00:00
timelineFirstId = _get_first_item_id(boxJson)
if timelineFirstId != prevTimelineFirstId:
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
None, system_language, espeak,
pageNumber,
newRepliesExist,
newDMsExist)
2021-04-01 16:30:13 +00:00
desktopShown = True
prevTimelineFirstId = timelineFirstId
2021-03-19 15:31:16 +00:00
else:
2021-12-28 16:56:57 +00:00
session = create_session(proxy_type)
2021-04-01 16:30:13 +00:00
if not desktopShown:
2021-04-01 16:36:45 +00:00
if not session:
print('No session\n')
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2021-04-01 16:33:30 +00:00
print('No posts\n')
2021-12-25 21:09:22 +00:00
if proxy_type == 'tor':
2021-04-04 11:58:48 +00:00
print('You may need to run the desktop client ' +
2021-04-01 16:49:37 +00:00
'with the --http option')
2021-03-04 13:57:30 +00:00
# wait for a while, or until a key is pressed
if noKeyPress:
time.sleep(10)
else:
2021-12-29 21:55:09 +00:00
commandStr = _desktop_wait_for_cmd(30, debug)
2021-03-17 10:04:49 +00:00
if commandStr:
2021-03-21 13:29:56 +00:00
refreshTimeline = False
2021-03-17 10:04:49 +00:00
if commandStr.startswith('/'):
commandStr = commandStr[1:]
if commandStr == 'q' or \
commandStr == 'quit' or \
commandStr == 'exit':
2021-03-10 10:46:50 +00:00
sayStr = 'Quit'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-03-10 18:31:45 +00:00
if screenreader:
2021-12-29 21:55:09 +00:00
commandStr = _desktop_wait_for_cmd(2, debug)
2021-03-04 18:05:46 +00:00
break
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('show dm'):
pageNumber = 1
prevTimelineFirstId = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'dm'
2021-12-29 21:55:09 +00:00
boxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, pageNumber,
debug, signing_priv_key_pem)
if boxJson:
2021-12-29 21:55:09 +00:00
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
screenreader, system_language, espeak,
pageNumber,
newRepliesExist, newDMsExist)
newDMsExist = False
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('show rep'):
pageNumber = 1
prevTimelineFirstId = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'tlreplies'
2021-12-29 21:55:09 +00:00
boxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, pageNumber,
debug, signing_priv_key_pem)
if boxJson:
2021-12-29 21:55:09 +00:00
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
screenreader, system_language, espeak,
pageNumber,
newRepliesExist, newDMsExist)
# Turn off the replies indicator
newRepliesExist = False
2021-03-19 21:34:38 +00:00
elif commandStr.startswith('show b'):
pageNumber = 1
prevTimelineFirstId = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'tlbookmarks'
2021-12-29 21:55:09 +00:00
boxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, pageNumber,
debug, signing_priv_key_pem)
2021-03-19 21:34:38 +00:00
if boxJson:
2021-12-29 21:55:09 +00:00
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
screenreader, system_language, espeak,
pageNumber,
newRepliesExist, newDMsExist)
2021-03-19 21:34:38 +00:00
# Turn off the replies indicator
newRepliesExist = False
2021-03-19 15:28:16 +00:00
elif (commandStr.startswith('show sen') or
commandStr.startswith('show out')):
pageNumber = 1
prevTimelineFirstId = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'outbox'
2021-12-29 21:55:09 +00:00
boxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, pageNumber,
debug, signing_priv_key_pem)
if boxJson:
2021-12-29 21:55:09 +00:00
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
screenreader, system_language, espeak,
pageNumber,
newRepliesExist, newDMsExist)
2021-03-17 10:04:49 +00:00
elif (commandStr == 'show' or commandStr.startswith('show in') or
commandStr == 'clear'):
pageNumber = 1
prevTimelineFirstId = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'inbox'
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('next'):
pageNumber += 1
prevTimelineFirstId = ''
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('prev'):
pageNumber -= 1
if pageNumber < 1:
pageNumber = 1
prevTimelineFirstId = ''
2021-12-29 21:55:09 +00:00
boxJson = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, pageNumber,
debug, signing_priv_key_pem)
if boxJson:
2021-12-29 21:55:09 +00:00
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
screenreader, system_language, espeak,
pageNumber,
newRepliesExist, newDMsExist)
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('read ') or commandStr == 'read':
if commandStr == 'read':
2021-03-16 14:06:05 +00:00
postIndexStr = '1'
else:
2021-03-17 10:04:49 +00:00
postIndexStr = commandStr.split('read ')[1]
if boxJson and postIndexStr.isdigit():
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2021-03-12 19:55:16 +00:00
postIndex = int(postIndexStr)
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_read_local_box_post(session, nickname, domain,
http_prefix, base_dir,
curr_timeline,
pageNumber, postIndex, boxJson,
system_language, screenreader,
espeak, translate, yourActor,
domain_full, person_cache,
signing_priv_key_pem,
blockedCache)
2021-03-25 10:56:41 +00:00
print('')
2021-03-25 14:15:36 +00:00
sayStr = 'Press Enter to continue...'
2021-12-29 21:55:09 +00:00
sayStr2 = _highlight_text(sayStr)
_say_command(sayStr2, sayStr,
screenreader, system_language, espeak)
input()
2021-03-25 10:56:41 +00:00
prevTimelineFirstId = ''
refreshTimeline = True
2021-03-12 19:55:16 +00:00
print('')
2021-03-22 18:27:48 +00:00
elif commandStr.startswith('profile ') or commandStr == 'profile':
2021-12-26 10:29:52 +00:00
actor_json = None
2021-03-22 18:27:48 +00:00
if commandStr == 'profile':
2021-12-25 22:09:19 +00:00
if post_json_object:
2021-12-26 10:29:52 +00:00
actor_json = \
2021-12-29 21:55:09 +00:00
_desktop_show_profile(session, nickname, domain,
http_prefix, base_dir,
curr_timeline,
pageNumber, postIndex,
boxJson,
system_language,
screenreader,
espeak, translate, yourActor,
post_json_object,
signing_priv_key_pem)
2021-03-23 16:17:03 +00:00
else:
postIndexStr = '1'
2021-03-22 18:27:48 +00:00
else:
postIndexStr = commandStr.split('profile ')[1]
2021-03-23 16:17:03 +00:00
2021-03-25 12:57:01 +00:00
if not postIndexStr.isdigit():
profileHandle = postIndexStr
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
_desktop_show_profile_from_handle(session,
nickname, domain,
http_prefix, base_dir,
curr_timeline,
profileHandle,
system_language,
screenreader,
espeak, translate,
yourActor,
None,
signing_priv_key_pem)
2021-03-25 14:15:36 +00:00
sayStr = 'Press Enter to continue...'
2021-12-29 21:55:09 +00:00
sayStr2 = _highlight_text(sayStr)
_say_command(sayStr2, sayStr,
screenreader, system_language, espeak)
2021-03-25 14:15:36 +00:00
input()
2021-03-25 14:18:19 +00:00
prevTimelineFirstId = ''
refreshTimeline = True
2021-12-26 10:29:52 +00:00
elif not actor_json and boxJson:
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2021-03-22 18:27:48 +00:00
postIndex = int(postIndexStr)
2021-12-26 10:29:52 +00:00
actor_json = \
2021-12-29 21:55:09 +00:00
_desktop_show_profile(session, nickname, domain,
http_prefix, base_dir,
curr_timeline,
pageNumber, postIndex,
boxJson,
system_language, screenreader,
espeak, translate, yourActor,
None, signing_priv_key_pem)
2021-03-25 14:15:36 +00:00
sayStr = 'Press Enter to continue...'
2021-12-29 21:55:09 +00:00
sayStr2 = _highlight_text(sayStr)
_say_command(sayStr2, sayStr,
screenreader, system_language, espeak)
2021-03-25 14:15:36 +00:00
input()
2021-03-25 14:18:19 +00:00
prevTimelineFirstId = ''
refreshTimeline = True
2021-03-22 18:27:48 +00:00
print('')
2021-03-17 10:04:49 +00:00
elif commandStr == 'reply' or commandStr == 'r':
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2021-12-26 19:47:06 +00:00
post_id = post_json_object['id']
subject = None
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('summary'):
subject = post_json_object['object']['summary']
2021-08-08 16:52:32 +00:00
conversationId = None
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('conversation'):
2021-08-08 16:52:32 +00:00
conversationId = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['conversation']
2021-12-28 16:56:57 +00:00
sessionReply = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
_desktop_reply_to_post(sessionReply, post_id,
base_dir, nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug, subject,
screenreader, system_language,
espeak, conversationId,
low_bandwidth,
content_license_url,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
print('')
2021-03-17 10:04:49 +00:00
elif (commandStr == 'post' or commandStr == 'p' or
commandStr == 'send' or
commandStr.startswith('dm ') or
commandStr.startswith('direct message ') or
commandStr.startswith('post ') or
commandStr.startswith('send ')):
2021-12-28 16:56:57 +00:00
sessionPost = create_session(proxy_type)
2021-03-17 10:04:49 +00:00
if commandStr.startswith('dm ') or \
commandStr.startswith('direct message ') or \
commandStr.startswith('post ') or \
commandStr.startswith('send '):
commandStr = commandStr.replace(' to ', ' ')
commandStr = commandStr.replace(' dm ', ' ')
commandStr = commandStr.replace(' DM ', ' ')
2021-03-11 12:24:20 +00:00
# direct message
2021-03-11 12:30:29 +00:00
toHandle = None
2021-03-17 10:04:49 +00:00
if commandStr.startswith('post '):
toHandle = commandStr.split('post ', 1)[1]
elif commandStr.startswith('send '):
toHandle = commandStr.split('send ', 1)[1]
elif commandStr.startswith('dm '):
toHandle = commandStr.split('dm ', 1)[1]
elif commandStr.startswith('direct message '):
toHandle = commandStr.split('direct message ', 1)[1]
2021-03-11 12:30:29 +00:00
if toHandle:
2021-12-29 21:55:09 +00:00
_desktop_new_dm(sessionPost, toHandle,
base_dir, nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug,
screenreader, system_language,
espeak, low_bandwidth,
content_license_url,
signing_priv_key_pem)
refreshTimeline = True
else:
# public post
_desktop_new_post(sessionPost,
2021-12-25 16:17:53 +00:00
base_dir, nickname, password,
2021-12-25 17:09:22 +00:00
domain, port, http_prefix,
2021-12-25 22:28:18 +00:00
cached_webfingers, person_cache,
2021-03-17 10:04:49 +00:00
debug,
2021-12-25 23:03:28 +00:00
screenreader, system_language,
2021-12-25 18:20:56 +00:00
espeak, low_bandwidth,
2021-12-25 17:13:38 +00:00
content_license_url,
2021-12-25 23:03:28 +00:00
signing_priv_key_pem)
2021-03-21 13:43:04 +00:00
refreshTimeline = True
2021-03-10 18:30:00 +00:00
print('')
2021-03-18 20:56:08 +00:00
elif commandStr == 'like' or commandStr.startswith('like '):
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
likeActor = post_json_object['object']['attributedTo']
sayStr = 'Liking post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(likeActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionLike = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_like_via_server(base_dir, sessionLike,
nickname, password,
domain, port, http_prefix,
post_json_object['id'],
cached_webfingers, person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
print('')
2021-03-21 12:31:48 +00:00
elif (commandStr == 'undo mute' or
commandStr == 'undo ignore' or
commandStr == 'remove mute' or
commandStr == 'rm mute' or
commandStr == 'unmute' or
commandStr == 'unignore' or
commandStr == 'mute undo' or
commandStr.startswith('undo mute ') or
commandStr.startswith('undo ignore ') or
commandStr.startswith('remove mute ') or
commandStr.startswith('remove ignore ') or
commandStr.startswith('unignore ') or
commandStr.startswith('unmute ')):
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
muteActor = post_json_object['object']['attributedTo']
2021-03-21 12:31:48 +00:00
sayStr = 'Unmuting post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(muteActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionMute = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_undo_mute_via_server(base_dir, sessionMute,
nickname, password,
domain, port,
http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-21 12:31:48 +00:00
print('')
elif (commandStr == 'mute' or
commandStr == 'ignore' or
commandStr.startswith('mute ') or
commandStr.startswith('ignore ')):
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
muteActor = post_json_object['object']['attributedTo']
2021-03-21 12:31:48 +00:00
sayStr = 'Muting post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(muteActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionMute = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_mute_via_server(base_dir, sessionMute,
nickname, password,
domain, port,
http_prefix,
post_json_object['id'],
cached_webfingers, person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-21 12:31:48 +00:00
print('')
2021-03-20 14:46:24 +00:00
elif (commandStr == 'undo bookmark' or
commandStr == 'remove bookmark' or
commandStr == 'rm bookmark' or
commandStr == 'undo bm' or
commandStr == 'rm bm' or
commandStr == 'remove bm' or
commandStr == 'unbookmark' or
commandStr == 'bookmark undo' or
commandStr == 'bm undo ' or
commandStr.startswith('undo bm ') or
commandStr.startswith('remove bm ') or
commandStr.startswith('undo bookmark ') or
commandStr.startswith('remove bookmark ') or
commandStr.startswith('unbookmark ') or
commandStr.startswith('unbm ')):
2021-03-19 22:04:57 +00:00
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
bmActor = post_json_object['object']['attributedTo']
2021-03-20 14:46:24 +00:00
sayStr = 'Unbookmarking post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(bmActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionbm = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_undo_bookmark_via_server(base_dir, sessionbm,
nickname, password,
domain, port,
http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-19 22:04:57 +00:00
print('')
2021-03-20 14:46:24 +00:00
elif (commandStr == 'bookmark' or
commandStr == 'bm' or
commandStr.startswith('bookmark ') or
commandStr.startswith('bm ')):
2021-03-19 22:11:45 +00:00
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
bmActor = post_json_object['object']['attributedTo']
2021-03-20 14:46:24 +00:00
sayStr = 'Bookmarking post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(bmActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionbm = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_bookmark_via_server(base_dir, sessionbm,
nickname, password,
domain, port, http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-19 22:11:45 +00:00
print('')
2021-03-23 14:16:44 +00:00
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:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id') and \
post_json_object.get('object'):
2021-12-26 10:57:03 +00:00
if has_object_dict(post_json_object):
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('attributedTo'):
2021-03-23 14:16:44 +00:00
blockActor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2021-03-23 14:16:44 +00:00
sayStr = 'Unblocking ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(blockActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionBlock = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
sign_priv_key_pem = signing_priv_key_pem
send_undo_block_via_server(base_dir,
sessionBlock,
nickname, password,
domain, port,
http_prefix,
blockActor,
cached_webfingers,
person_cache,
False, __version__,
sign_priv_key_pem)
2021-03-23 14:16:44 +00:00
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 = \
2021-12-26 10:19:59 +00:00
local_actor_url(http_prefix,
blockNickname,
blockDomain)
2021-03-23 14:16:44 +00:00
if currIndex > 0 and boxJson and not blockActor:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object and not blockActor:
if post_json_object.get('id') and \
post_json_object.get('object'):
2021-12-26 10:57:03 +00:00
if has_object_dict(post_json_object):
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('attributedTo'):
2021-03-23 14:16:44 +00:00
blockActor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2021-03-23 14:16:44 +00:00
if blockActor:
sayStr = 'Blocking ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(blockActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionBlock = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_block_via_server(base_dir, sessionBlock,
nickname, password,
domain, port,
http_prefix,
blockActor,
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-23 14:16:44 +00:00
refreshTimeline = True
print('')
elif commandStr == 'unlike' or commandStr == 'undo like':
2021-03-18 20:56:08 +00:00
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
unlikeActor = \
post_json_object['object']['attributedTo']
sayStr = \
'Undoing like of post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(unlikeActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionUnlike = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_undo_like_via_server(base_dir, sessionUnlike,
nickname, password,
domain, port, http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
print('')
2021-03-18 20:56:08 +00:00
elif (commandStr.startswith('announce') or
commandStr.startswith('boost') or
commandStr.startswith('retweet')):
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2021-12-26 19:47:06 +00:00
post_id = post_json_object['id']
announceActor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
sayStr = 'Announcing post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(announceActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionAnnounce = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_announce_via_server(base_dir, sessionAnnounce,
nickname, password,
domain, port,
http_prefix, post_id,
cached_webfingers,
person_cache,
True, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
print('')
2021-03-18 20:56:08 +00:00
elif (commandStr.startswith('unannounce') or
commandStr.startswith('undo announce') or
commandStr.startswith('unboost') or
commandStr.startswith('undo boost') or
commandStr.startswith('undo retweet')):
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2021-12-26 19:47:06 +00:00
post_id = post_json_object['id']
2021-03-18 20:56:08 +00:00
announceActor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2021-03-18 20:56:08 +00:00
sayStr = 'Undoing announce post by ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(announceActor)
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionAnnounce = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_undo_announce_via_server(base_dir,
sessionAnnounce,
post_json_object,
nickname, password,
domain, port,
http_prefix, post_id,
cached_webfingers,
person_cache,
True, __version__,
signing_priv_key_pem)
2021-03-21 13:29:56 +00:00
refreshTimeline = True
2021-03-18 20:56:08 +00:00
print('')
elif (commandStr == 'follow requests' or
commandStr.startswith('follow requests ')):
currPage = 1
if ' ' in commandStr:
pageNum = commandStr.split(' ')[-1].strip()
if pageNum.isdigit():
currPage = int(pageNum)
followRequestsJson = \
2021-12-29 21:55:09 +00:00
get_follow_requests_via_server(base_dir, session,
nickname, password,
domain, port,
http_prefix, currPage,
cached_webfingers,
person_cache,
debug, __version__,
signing_priv_key_pem)
if followRequestsJson:
if isinstance(followRequestsJson, dict):
2021-12-29 21:55:09 +00:00
_desktop_show_follow_requests(followRequestsJson,
translate)
print('')
elif (commandStr == 'following' or
commandStr.startswith('following ')):
currPage = 1
if ' ' in commandStr:
pageNum = commandStr.split(' ')[-1].strip()
if pageNum.isdigit():
currPage = int(pageNum)
followingJson = \
2021-12-29 21:55:09 +00:00
get_following_via_server(base_dir, session,
nickname, password,
domain, port,
http_prefix, currPage,
cached_webfingers, person_cache,
debug, __version__,
signing_priv_key_pem)
if followingJson:
if isinstance(followingJson, dict):
2021-12-29 21:55:09 +00:00
_desktop_show_following(followingJson, translate,
currPage, indent,
'following')
print('')
elif (commandStr == 'followers' or
commandStr.startswith('followers ')):
currPage = 1
if ' ' in commandStr:
pageNum = commandStr.split(' ')[-1].strip()
if pageNum.isdigit():
currPage = int(pageNum)
followersJson = \
2021-12-29 21:55:09 +00:00
get_followers_via_server(base_dir, session,
nickname, password,
domain, port,
http_prefix, currPage,
cached_webfingers, person_cache,
debug, __version__,
signing_priv_key_pem)
if followersJson:
if isinstance(followersJson, dict):
2021-12-29 21:55:09 +00:00
_desktop_show_following(followersJson, translate,
currPage, indent,
'followers')
print('')
2021-03-22 18:27:48 +00:00
elif (commandStr == 'follow' or
commandStr.startswith('follow ')):
if commandStr == 'follow':
2021-12-26 10:29:52 +00:00
if actor_json:
followHandle = actor_json['id']
2021-03-22 18:27:48 +00:00
else:
followHandle = ''
else:
followHandle = commandStr.replace('follow ', '').strip()
if followHandle.startswith('@'):
followHandle = followHandle[1:]
if '@' in followHandle or '://' in followHandle:
2021-12-27 22:19:18 +00:00
followNickname = get_nickname_from_actor(followHandle)
followDomain, followPort = \
2021-12-27 19:05:25 +00:00
get_domain_from_actor(followHandle)
if followNickname and followDomain:
sayStr = 'Sending follow request to ' + \
followNickname + '@' + followDomain
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader, system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionFollow = create_session(proxy_type)
2021-12-28 20:32:11 +00:00
send_follow_requestViaServer(base_dir,
sessionFollow,
nickname, password,
domain, port,
followNickname,
followDomain,
followPort,
http_prefix,
cached_webfingers,
person_cache,
debug, __version__,
signing_priv_key_pem)
else:
2021-03-22 18:27:48 +00:00
if followHandle:
sayStr = followHandle + ' is not valid'
else:
sayStr = 'Specify a handle to follow'
2021-12-29 21:55:09 +00:00
_say_command(sayStr,
screenreader, system_language, espeak)
print('')
2021-03-17 10:04:49 +00:00
elif (commandStr.startswith('unfollow ') or
commandStr.startswith('stop following ')):
followHandle = commandStr.replace('unfollow ', '').strip()
followHandle = followHandle.replace('stop following ', '')
if followHandle.startswith('@'):
followHandle = followHandle[1:]
if '@' in followHandle or '://' in followHandle:
2021-12-27 22:19:18 +00:00
followNickname = get_nickname_from_actor(followHandle)
followDomain, followPort = \
2021-12-27 19:05:25 +00:00
get_domain_from_actor(followHandle)
if followNickname and followDomain:
sayStr = 'Stop following ' + \
followNickname + '@' + followDomain
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader, system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionUnfollow = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_unfollow_request_via_server(base_dir,
sessionUnfollow,
nickname, password,
domain, port,
followNickname,
followDomain,
followPort,
http_prefix,
cached_webfingers,
person_cache,
debug, __version__,
signing_priv_key_pem)
else:
sayStr = followHandle + ' is not valid'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader, system_language, espeak)
print('')
elif commandStr.startswith('approve '):
approveHandle = commandStr.replace('approve ', '').strip()
if approveHandle.startswith('@'):
approveHandle = approveHandle[1:]
if '@' in approveHandle or '://' in approveHandle:
2021-12-27 22:19:18 +00:00
approveNickname = get_nickname_from_actor(approveHandle)
approveDomain, approvePort = \
2021-12-27 19:05:25 +00:00
get_domain_from_actor(approveHandle)
if approveNickname and approveDomain:
sayStr = 'Sending approve follow request for ' + \
approveNickname + '@' + approveDomain
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader, system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionApprove = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
approve_follow_request_via_server(base_dir,
sessionApprove,
nickname, password,
domain, port,
http_prefix,
approveHandle,
cached_webfingers,
person_cache,
debug,
__version__,
signing_priv_key_pem)
else:
if approveHandle:
sayStr = approveHandle + ' is not valid'
else:
sayStr = 'Specify a handle to approve'
2021-12-29 21:55:09 +00:00
_say_command(sayStr,
screenreader, system_language, espeak)
print('')
elif commandStr.startswith('deny '):
denyHandle = commandStr.replace('deny ', '').strip()
if denyHandle.startswith('@'):
denyHandle = denyHandle[1:]
if '@' in denyHandle or '://' in denyHandle:
2021-12-27 22:19:18 +00:00
denyNickname = get_nickname_from_actor(denyHandle)
denyDomain, denyPort = \
2021-12-27 19:05:25 +00:00
get_domain_from_actor(denyHandle)
if denyNickname and denyDomain:
sayStr = 'Sending deny follow request for ' + \
denyNickname + '@' + denyDomain
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader, system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionDeny = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
deny_follow_request_via_server(base_dir, sessionDeny,
nickname, password,
domain, port,
http_prefix,
denyHandle,
cached_webfingers,
person_cache,
debug,
__version__,
signing_priv_key_pem)
else:
if denyHandle:
sayStr = denyHandle + ' is not valid'
else:
sayStr = 'Specify a handle to deny'
2021-12-29 21:55:09 +00:00
_say_command(sayStr,
screenreader, system_language, espeak)
print('')
2021-03-17 10:04:49 +00:00
elif (commandStr == 'repeat' or commandStr == 'replay' or
commandStr == 'rp' or commandStr == 'again' or
commandStr == 'say again'):
2021-03-11 11:09:33 +00:00
if screenreader and nameStr and \
gender and messageStr and content:
sayStr = 'Repeating ' + nameStr
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak,
nameStr, gender)
2021-03-10 12:37:44 +00:00
time.sleep(2)
2021-12-29 21:55:09 +00:00
_say_command(content, messageStr, screenreader,
system_language, espeak,
nameStr, gender)
2021-03-10 12:40:17 +00:00
print('')
2021-03-17 10:04:49 +00:00
elif (commandStr == 'sounds on' or
commandStr == 'sound on' or
commandStr == 'sound'):
2021-03-10 10:34:06 +00:00
sayStr = 'Notification sounds on'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
notificationSounds = True
2021-03-17 10:04:49 +00:00
elif (commandStr == 'sounds off' or
commandStr == 'sound off' or
commandStr == 'nosound'):
2021-03-10 10:34:06 +00:00
sayStr = 'Notification sounds off'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
notificationSounds = False
2021-03-17 10:04:49 +00:00
elif (commandStr == 'speak' or
commandStr == 'screen reader on' or
commandStr == 'speaker on' or
commandStr == 'talker on' or
commandStr == 'reader on'):
2021-03-10 10:25:41 +00:00
if originalScreenReader:
screenreader = originalScreenReader
2021-03-10 10:34:06 +00:00
sayStr = 'Screen reader on'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-03-10 10:25:41 +00:00
else:
print('No --screenreader option was specified')
2021-03-17 10:04:49 +00:00
elif (commandStr == 'mute' or
commandStr == 'screen reader off' or
commandStr == 'speaker off' or
commandStr == 'talker off' or
commandStr == 'reader off'):
2021-03-10 10:25:41 +00:00
if originalScreenReader:
screenreader = None
2021-03-10 10:34:06 +00:00
sayStr = 'Screen reader off'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, originalScreenReader,
system_language, espeak)
2021-03-10 10:25:41 +00:00
else:
print('No --screenreader option was specified')
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('open'):
2021-03-15 17:00:23 +00:00
currIndex = 0
2021-03-17 10:04:49 +00:00
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
2021-03-15 17:00:23 +00:00
if postIndex.isdigit():
currIndex = int(postIndex)
2021-03-18 19:04:58 +00:00
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object['type'] == 'Announce':
2021-12-26 20:01:37 +00:00
recent_posts_cache = {}
2021-12-25 18:54:50 +00:00
allow_local_network_access = False
2021-12-25 17:15:52 +00:00
yt_replace_domain = None
2021-12-25 20:55:47 +00:00
twitter_replacement_domain = None
2021-12-25 22:09:19 +00:00
post_json_object2 = \
2021-12-29 21:55:09 +00:00
download_announce(session, base_dir,
http_prefix,
nickname, domain,
post_json_object,
__version__, translate,
yt_replace_domain,
twitter_replacement_domain,
allow_local_network_access,
recent_posts_cache, False,
system_language,
domain_full, person_cache,
signing_priv_key_pem,
blockedCache)
2021-12-25 22:09:19 +00:00
if post_json_object2:
post_json_object = post_json_object2
if post_json_object:
content = \
2021-12-26 11:29:40 +00:00
get_base_content_from_post(post_json_object,
system_language)
2021-03-18 19:04:58 +00:00
messageStr, detectedLinks = \
2021-12-29 21:55:09 +00:00
speakable_text(base_dir, content, translate)
2021-03-18 19:04:58 +00:00
linkOpened = False
for url in detectedLinks:
if '://' in url:
webbrowser.open(url)
linkOpened = True
if linkOpened:
sayStr = 'Opened web links'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, originalScreenReader,
system_language, espeak)
2021-03-18 19:04:58 +00:00
else:
sayStr = 'There are no web links to open.'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, originalScreenReader,
system_language, espeak)
print('')
2021-05-05 09:53:00 +00:00
elif commandStr.startswith('pgp') or commandStr.startswith('gpg'):
2021-12-29 21:55:09 +00:00
if not has_local_pg_pkey():
2021-05-05 09:53:00 +00:00
print('No PGP public key was found')
else:
2021-12-29 21:55:09 +00:00
print(pgp_local_public_key())
2021-05-05 09:53:00 +00:00
print('')
2021-03-17 10:04:49 +00:00
elif commandStr.startswith('h'):
2021-12-29 21:55:09 +00:00
_desktop_help()
2021-03-25 14:15:36 +00:00
sayStr = 'Press Enter to continue...'
2021-12-29 21:55:09 +00:00
sayStr2 = _highlight_text(sayStr)
_say_command(sayStr2, sayStr,
screenreader, system_language, espeak)
2021-03-25 12:21:04 +00:00
input()
2021-03-25 15:11:52 +00:00
prevTimelineFirstId = ''
refreshTimeline = True
2021-03-21 18:37:06 +00:00
elif (commandStr == 'delete' or
commandStr == 'rm' or
commandStr.startswith('delete ') or
commandStr.startswith('rm ')):
currIndex = 0
if ' ' in commandStr:
postIndex = commandStr.split(' ')[-1].strip()
if postIndex.isdigit():
currIndex = int(postIndex)
if currIndex > 0 and boxJson:
2021-12-25 22:09:19 +00:00
post_json_object = \
2021-12-29 21:55:09 +00:00
_desktop_get_box_post_object(boxJson, currIndex)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
rmActor = post_json_object['object']['attributedTo']
if rmActor != yourActor:
2021-03-21 18:37:06 +00:00
sayStr = 'You can only delete your own posts'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-03-21 18:37:06 +00:00
else:
2021-03-21 20:05:06 +00:00
print('')
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('summary'):
print(post_json_object['object']['summary'])
contentStr = \
2021-12-26 11:29:40 +00:00
get_base_content_from_post(post_json_object,
system_language)
print(contentStr)
2021-03-21 20:05:06 +00:00
print('')
sayStr = 'Confirm delete, yes or no?'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr, screenreader,
system_language, espeak)
2021-03-21 20:05:06 +00:00
yesno = input()
if 'y' not in yesno.lower():
sayStr = 'Deleting post'
2021-12-29 21:55:09 +00:00
_say_command(sayStr, sayStr,
screenreader,
system_language, espeak)
2021-12-28 16:56:57 +00:00
sessionrm = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_delete_via_server(base_dir, sessionrm,
nickname, password,
domain, port,
http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2021-03-21 20:05:06 +00:00
refreshTimeline = True
2021-03-21 18:37:06 +00:00
print('')
2021-03-21 13:29:56 +00:00
if refreshTimeline:
if boxJson:
2021-12-29 21:55:09 +00:00
_desktop_show_box(indent, followRequestsJson,
yourActor, curr_timeline, boxJson,
translate,
screenreader, system_language,
espeak, pageNumber,
newRepliesExist, newDMsExist)