epicyon/desktop_client.py

2568 lines
114 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+"
2022-02-03 13:58:20 +00:00
__version__ = "1.3.0"
2021-03-04 13:57:30 +00:00
__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
2022-03-13 12:15:52 +00:00
from follow import send_follow_request_via_server
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
"""
2022-01-02 12:23:59 +00:00
home_dir = str(Path.home())
if not os.path.isdir(home_dir + '/.config'):
os.mkdir(home_dir + '/.config')
if not os.path.isdir(home_dir + '/.config/epicyon'):
os.mkdir(home_dir + '/.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
2022-01-02 12:23:59 +00:00
if port not in (443, 80):
handle += '_' + str(port)
2022-01-02 12:23:59 +00:00
read_posts_dir = home_dir + '/.config/epicyon/' + handle
if not os.path.isdir(read_posts_dir):
os.mkdir(read_posts_dir)
2022-01-02 12:23:59 +00:00
def _mark_post_as_read(actor: str, post_id: str, post_category: str) -> None:
"""Marks the given post as read by the given actor
"""
2022-01-02 12:23:59 +00:00
home_dir = 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
2022-01-02 12:23:59 +00:00
if port not in (443, 80):
handle += '_' + str(port)
2022-01-02 12:23:59 +00:00
read_posts_dir = home_dir + '/.config/epicyon/' + handle
read_posts_filename = read_posts_dir + '/' + post_category + '.txt'
if os.path.isfile(read_posts_filename):
if post_id in open(read_posts_filename).read():
return
try:
# prepend to read posts file
2021-12-26 19:47:06 +00:00
post_id += '\n'
2022-01-02 12:23:59 +00:00
with open(read_posts_filename, 'r+') as read_file:
content = read_file.read()
2021-12-26 19:47:06 +00:00
if post_id not in content:
2022-01-02 12:23:59 +00:00
read_file.seek(0, 0)
read_file.write(post_id + content)
2021-12-25 15:28:52 +00:00
except Exception as ex:
2022-02-03 10:39:52 +00:00
print('EX: Failed to mark post as read' + str(ex))
else:
2022-01-02 12:23:59 +00:00
with open(read_posts_filename, 'w+') as read_file:
read_file.write(post_id + '\n')
2022-01-02 12:23:59 +00:00
def _has_read_post(actor: str, post_id: str, post_category: str) -> bool:
"""Returns true if the given post has been read by the actor
"""
2022-01-02 12:23:59 +00:00
home_dir = 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
2022-01-02 12:23:59 +00:00
if port not in (443, 80):
handle += '_' + str(port)
2022-01-02 12:23:59 +00:00
read_posts_dir = home_dir + '/.config/epicyon/' + handle
read_posts_filename = read_posts_dir + '/' + post_category + '.txt'
if os.path.isfile(read_posts_filename):
if post_id in open(read_posts_filename).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
"""
2022-01-02 12:23:59 +00:00
to_your_actor = False
2021-12-25 22:09:19 +00:00
if post_json_object.get('to'):
if actor in post_json_object['to']:
2022-01-02 12:23:59 +00:00
to_your_actor = True
if not to_your_actor and post_json_object.get('cc'):
2021-12-25 22:09:19 +00:00
if actor in post_json_object['cc']:
2022-01-02 12:23:59 +00:00
to_your_actor = True
if not to_your_actor 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']:
2022-01-02 12:23:59 +00:00
to_your_actor = True
if not to_your_actor and post_json_object['object'].get('cc'):
2021-12-25 22:09:19 +00:00
if actor in post_json_object['object']['cc']:
2022-01-02 12:23:59 +00:00
to_your_actor = True
return to_your_actor
2022-01-02 12:23:59 +00:00
def _new_desktop_notifications(actor: str, inbox_json: {},
notify_json: {}) -> None:
"""Looks for changes in the inbox and adds notifications
"""
2022-01-02 12:23:59 +00:00
notify_json['dmNotifyChanged'] = False
notify_json['repliesNotifyChanged'] = False
if not inbox_json:
return
2022-01-02 12:23:59 +00:00
if not inbox_json.get('orderedItems'):
return
2022-01-02 12:23:59 +00:00
dm_done = False
reply_done = False
for post_json_object in inbox_json['orderedItems']:
2021-12-25 22:09:19 +00:00
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):
2022-01-02 12:23:59 +00:00
if not dm_done:
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
2022-01-02 12:23:59 +00:00
if not notify_json.get('dmPostId'):
2021-03-23 10:03:45 +00:00
changed = True
else:
2022-01-02 12:23:59 +00:00
if notify_json['dmPostId'] != post_json_object['id']:
2021-03-23 10:03:45 +00:00
changed = True
if changed:
2022-01-02 12:23:59 +00:00
notify_json['dmNotify'] = True
notify_json['dmNotifyChanged'] = True
notify_json['dmPostId'] = post_json_object['id']
dm_done = True
else:
2022-01-02 12:23:59 +00:00
if not reply_done:
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
2022-01-02 12:23:59 +00:00
if not notify_json.get('repliesPostId'):
2021-03-23 10:03:45 +00:00
changed = True
else:
2022-01-02 12:23:59 +00:00
if notify_json['repliesPostId'] != \
2021-12-25 22:09:19 +00:00
post_json_object['id']:
2021-03-23 10:03:45 +00:00
changed = True
if changed:
2022-01-02 12:23:59 +00:00
notify_json['repliesNotify'] = True
notify_json['repliesNotifyChanged'] = True
notify_json['repliesPostId'] = post_json_object['id']
reply_done = 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-12-31 21:18:12 +00:00
banner_filename = 'banner.txt'
if not os.path.isfile(banner_filename):
2022-01-02 12:23:59 +00:00
banner_theme = 'starlight'
banner_filename = 'theme/' + banner_theme + '/banner.txt'
2021-12-31 21:18:12 +00:00
if not os.path.isfile(banner_filename):
2021-03-15 14:36:03 +00:00
return
2021-12-31 21:18:12 +00:00
with open(banner_filename, 'r') as banner_file:
banner = banner_file.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
"""
2022-01-02 12:23:59 +00:00
inp, _, _ = select.select([sys.stdin], [], [], timeout)
2021-03-04 15:21:38 +00:00
2022-01-02 12:23:59 +00:00
if inp:
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
2022-01-02 12:23:59 +00:00
if debug:
print("Timeout")
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,
2022-01-02 12:23:59 +00:00
say_text: 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)
2022-01-02 12:23:59 +00:00
espeak.synth(html.unescape(say_text))
2021-03-04 14:54:30 +00:00
2021-12-29 21:55:09 +00:00
def _speaker_picospeaker(pitch: int, rate: int, system_language: str,
2022-01-02 12:23:59 +00:00
say_text: str) -> None:
2021-03-16 10:37:51 +00:00
"""TTS using picospeaker
"""
2022-01-02 12:23:59 +00:00
speaker_lang = 'en-GB'
supported_languages = {
2021-12-13 15:49:28 +00:00
"fr": "fr-FR",
"es": "es-ES",
"de": "de-DE",
"it": "it-IT"
}
2022-01-02 12:23:59 +00:00
for lang, speaker_str in supported_languages.items():
2021-12-25 23:03:28 +00:00
if system_language.startswith(lang):
2022-01-02 12:23:59 +00:00
speaker_lang = speaker_str
2021-12-13 15:49:28 +00:00
break
2022-01-02 12:23:59 +00:00
say_text = str(say_text).replace('"', "'")
speaker_cmd = 'picospeaker ' + \
'-l ' + speaker_lang + \
2021-03-04 14:54:30 +00:00
' -r ' + str(rate) + \
' -p ' + str(pitch) + ' "' + \
2022-01-02 12:23:59 +00:00
html.unescape(str(say_text)) + '" 2> /dev/null'
os.system(speaker_cmd)
2021-03-04 14:54:30 +00:00
2022-01-02 12:23:59 +00:00
def _play_notification_sound(sound_filename: str,
2021-12-29 21:55:09 +00:00
player: str = 'ffplay') -> None:
2021-03-09 19:52:10 +00:00
"""Plays a sound
"""
2022-01-02 12:23:59 +00:00
if not os.path.isfile(sound_filename):
2021-03-09 19:52:10 +00:00
return
if player == 'ffplay':
2022-01-02 12:23:59 +00:00
os.system('ffplay ' + sound_filename +
2021-03-10 15:43:21 +00:00
' -autoexit -hide_banner -nodisp 2> /dev/null')
2021-03-09 19:52:10 +00:00
2022-01-02 12:23:59 +00:00
def _desktop_notification(notification_type: str,
2021-12-29 21:55:09 +00:00
title: str, message: str) -> None:
2021-03-09 20:32:50 +00:00
"""Shows a desktop notification
"""
2022-01-02 12:23:59 +00:00
if not notification_type:
2021-03-09 20:32:50 +00:00
return
2022-01-02 12:23:59 +00:00
if notification_type == 'notify-send':
2021-03-09 20:32:50 +00:00
# Ubuntu
os.system('notify-send "' + title + '" "' + message + '"')
2022-01-02 12:23:59 +00:00
elif notification_type == 'zenity':
2021-03-11 10:01:05 +00:00
# Zenity
os.system('zenity --notification --title "' + title +
'" --text="' + message + '"')
2022-01-02 12:23:59 +00:00
elif notification_type == 'osascript':
2021-03-09 20:32:50 +00:00
# Mac
os.system("osascript -e 'display notification \"" +
message + "\" with title \"" + title + "\"'")
2022-01-02 12:23:59 +00:00
elif notification_type == 'New-BurntToastNotification':
2021-03-09 20:32:50 +00:00
# Windows
os.system("New-BurntToastNotification -Text \"" +
title + "\", '" + message + "'")
2022-01-02 12:23:59 +00:00
def _text_to_speech(say_str: str, screenreader: str,
2021-12-29 21:55:09 +00:00
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':
2022-01-02 12:23:59 +00:00
_speaker_espeak(espeak, pitch, rate, srange, say_str)
2021-03-10 12:11:42 +00:00
elif screenreader == 'picospeaker':
2022-01-02 12:23:59 +00:00
_speaker_picospeaker(pitch, rate, system_language, say_str)
2021-03-10 12:11:42 +00:00
2022-01-02 12:23:59 +00:00
def _say_command(content: str, say_str: str, screenreader: str,
system_language: str, espeak=None,
speaker_name: str = 'screen reader',
speaker_gender: 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
2022-01-02 12:23:59 +00:00
pitch = get_speaker_pitch(speaker_name,
screenreader, speaker_gender)
rate = get_speaker_rate(speaker_name, screenreader)
srange = get_speaker_range(speaker_name)
2021-12-29 21:55:09 +00:00
2022-01-02 12:23:59 +00:00
_text_to_speech(say_str, screenreader,
2021-12-29 21:55:09 +00:00
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,
languages_understood: [],
2022-01-02 12:23:59 +00:00
espeak, conversation_id: str,
2021-12-29 21:55:09 +00:00
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
2022-01-02 12:23:59 +00:00
to_nickname = get_nickname_from_actor(post_id)
to_domain, to_port = get_domain_from_actor(post_id)
say_str = 'Replying to ' + to_nickname + '@' + to_domain
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2022-01-02 12:23:59 +00:00
say_str = 'Type your reply message, then press Enter.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
reply_message = input()
if not reply_message:
say_str = 'No reply was entered.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
return
2022-01-02 12:23:59 +00:00
reply_message = reply_message.strip()
if not reply_message:
say_str = 'No reply was entered.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
return
print('')
2022-01-02 12:23:59 +00:00
say_str = 'You entered this reply:'
_say_command(say_str, say_str, screenreader, system_language, espeak)
_say_command(reply_message, reply_message, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2022-01-02 12:23:59 +00:00
say_str = 'Send this reply, yes or no?'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
yesno = input()
if 'y' not in yesno.lower():
2022-01-02 12:23:59 +00:00
say_str = 'Abandoning reply'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-10 18:30:00 +00:00
return
2022-01-02 12:23:59 +00:00
cc_url = None
followers_only = False
attach = None
2022-01-02 12:23:59 +00:00
media_type = None
attached_image_description = None
is_article = False
subject = None
2022-01-02 12:23:59 +00:00
comments_enabled = True
2021-05-09 19:29:53 +00:00
city = 'London, England'
2022-01-02 12:23:59 +00:00
say_str = 'Sending reply'
event_date = None
event_time = None
location = None
2022-01-02 12:23:59 +00:00
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-12-29 21:55:09 +00:00
if send_post_via_server(signing_priv_key_pem, __version__,
base_dir, session, nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
to_nickname, to_domain, to_port, cc_url,
http_prefix, reply_message, followers_only,
comments_enabled, attach, media_type,
attached_image_description, city,
cached_webfingers, person_cache, is_article,
system_language, languages_understood,
low_bandwidth, content_license_url,
event_date, event_time, location,
2021-12-29 21:55:09 +00:00
debug, post_id, post_id,
2022-01-02 12:23:59 +00:00
conversation_id, subject) == 0:
say_str = 'Reply sent'
2021-03-10 19:31:33 +00:00
else:
2022-01-02 12:23:59 +00:00
say_str = 'Reply failed'
_say_command(say_str, say_str, 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,
languages_understood: [],
2021-12-29 21:55:09 +00:00
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
"""
2022-01-02 12:23:59 +00:00
conversation_id = None
say_str = 'Create new post'
_say_command(say_str, say_str, screenreader, system_language, espeak)
say_str = 'Type your post, then press Enter.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
new_message = input()
if not new_message:
say_str = 'No post was entered.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
return
2022-01-02 12:23:59 +00:00
new_message = new_message.strip()
if not new_message:
say_str = 'No post was entered.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
return
2021-03-21 13:43:04 +00:00
print('')
2022-01-02 12:23:59 +00:00
say_str = 'You entered this public post:'
_say_command(say_str, say_str, screenreader, system_language, espeak)
_say_command(new_message, new_message,
screenreader, system_language, espeak)
say_str = 'Send this post, yes or no?'
_say_command(say_str, say_str, screenreader, system_language, espeak)
yesno = input()
if 'y' not in yesno.lower():
2022-01-02 12:23:59 +00:00
say_str = 'Abandoning new post'
_say_command(say_str, say_str, screenreader, system_language, espeak)
return
2022-01-02 12:23:59 +00:00
cc_url = None
followers_only = False
attach = None
2022-01-02 12:23:59 +00:00
media_type = None
attached_image_description = None
2021-05-09 19:29:53 +00:00
city = 'London, England'
2022-01-02 12:23:59 +00:00
is_article = False
subject = None
2022-01-02 12:23:59 +00:00
comments_enabled = True
subject = None
2022-01-02 12:23:59 +00:00
say_str = 'Sending'
event_date = None
event_time = None
location = None
2022-01-02 12:23:59 +00:00
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-12-29 21:55:09 +00:00
if send_post_via_server(signing_priv_key_pem, __version__,
base_dir, session, nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
None, '#Public', port, cc_url,
http_prefix, new_message, followers_only,
comments_enabled, attach, media_type,
attached_image_description, city,
cached_webfingers, person_cache, is_article,
system_language, languages_understood,
low_bandwidth, content_license_url,
event_date, event_time, location,
2021-12-29 21:55:09 +00:00
debug, None, None,
2022-01-02 12:23:59 +00:00
conversation_id, subject) == 0:
say_str = 'Post sent'
else:
2022-01-02 12:23:59 +00:00
say_str = 'Post failed'
_say_command(say_str, say_str, 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('$(', '$ (')
2022-01-02 12:23:59 +00:00
def _timeline_is_empty(box_json: {}) -> bool:
"""Returns true if the given timeline is empty
"""
empty = False
2022-01-02 12:23:59 +00:00
if not box_json:
empty = True
else:
2022-01-02 12:23:59 +00:00
if not isinstance(box_json, dict):
empty = True
2022-01-02 12:23:59 +00:00
elif not box_json.get('orderedItems'):
empty = True
return empty
2022-01-02 12:23:59 +00:00
def _get_first_item_id(box_json: {}) -> str:
"""Returns the id of the first item in the timeline
"""
2022-01-02 12:23:59 +00:00
if _timeline_is_empty(box_json):
return
2022-01-02 12:23:59 +00:00
if len(box_json['orderedItems']) == 0:
return
2022-01-02 12:23:59 +00:00
return box_json['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
"""
2022-01-02 12:23:59 +00:00
image_description = ''
2021-12-25 22:09:19 +00:00
if not post_json_object['object'].get('attachment'):
2022-01-02 12:23:59 +00:00
return image_description
2021-03-19 14:49:40 +00:00
2022-01-02 12:23:59 +00:00
attach_list = post_json_object['object']['attachment']
if not isinstance(attach_list, list):
return image_description
2021-03-19 14:49:40 +00:00
# for each attachment
2022-01-02 12:23:59 +00:00
for img in attach_list:
2021-03-19 14:49:40 +00:00
if not isinstance(img, dict):
continue
if not img.get('name'):
continue
if not isinstance(img['name'], str):
continue
2022-01-02 12:23:59 +00:00
message_str = img['name']
if message_str:
message_str = message_str.strip()
if not message_str.endswith('.'):
image_description += message_str + '. '
2021-03-19 14:49:40 +00:00
else:
2022-01-02 12:23:59 +00:00
image_description += message_str + ' '
return image_description
2021-03-19 14:49:40 +00:00
2022-01-02 12:23:59 +00:00
def _show_likes_on_post(post_json_object: {}, max_likes: 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
2022-01-02 12:23:59 +00:00
object_likes = post_json_object['object']['likes']
if not isinstance(object_likes, dict):
2021-03-23 14:36:35 +00:00
return
2022-01-02 12:23:59 +00:00
if not object_likes.get('items'):
2021-03-23 14:36:35 +00:00
return
2022-01-02 12:23:59 +00:00
if not isinstance(object_likes['items'], list):
2021-03-23 14:50:40 +00:00
return
2021-03-23 14:36:35 +00:00
print('')
ctr = 0
2022-01-02 12:23:59 +00:00
for item in object_likes['items']:
2021-03-23 14:36:35 +00:00
print('' + str(item['actor']))
ctr += 1
2022-01-02 12:23:59 +00:00
if ctr >= max_likes:
2021-03-23 14:36:35 +00:00
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
2022-01-02 12:23:59 +00:00
object_replies = post_json_object['object']['replies']
if not isinstance(object_replies, dict):
2021-03-23 19:14:49 +00:00
return
2022-01-02 12:23:59 +00:00
if not object_replies.get('items'):
2021-03-23 19:14:49 +00:00
return
2022-01-02 12:23:59 +00:00
if not isinstance(object_replies['items'], list):
2021-03-23 19:14:49 +00:00
return
print('')
ctr = 0
2022-01-02 12:23:59 +00:00
for item in object_replies['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,
2022-01-02 12:23:59 +00:00
http_prefix: str, base_dir: str, box_name: str,
page_number: int, index: int, box_json: {},
2021-12-29 21:55:09 +00:00
system_language: str,
screenreader: str, espeak,
2022-01-02 12:23:59 +00:00
translate: {}, your_actor: str,
2021-12-29 21:55:09 +00:00
domain_full: str, person_cache: {},
signing_priv_key_pem: str,
2022-03-24 14:40:28 +00:00
blocked_cache: {}, bold_reading: bool) -> {}:
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
"""
2022-01-02 12:23:59 +00:00
if _timeline_is_empty(box_json):
return {}
2021-03-12 19:55:16 +00:00
2022-01-02 12:23:59 +00:00
post_json_object = _desktop_get_box_post_object(box_json, 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'
2022-01-02 12:23:59 +00:00
box_name_str = box_name
if box_name.startswith('tl'):
box_name_str = box_name[2:]
say_str = 'Reading ' + box_name_str + ' post ' + str(index) + \
' from page ' + str(page_number) + '.'
say_str2 = say_str.replace(' dm ', ' DM ')
_say_command(say_str, say_str2, 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']
2022-01-02 12:23:59 +00:00
name_str = 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,
2022-03-24 14:40:28 +00:00
blocked_cache, bold_reading)
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'):
2022-01-02 12:23:59 +00:00
attributed_to = post_json_object2['object']['attributedTo']
content = \
2021-12-26 11:29:40 +00:00
get_base_content_from_post(post_json_object2,
system_language)
2022-01-02 12:23:59 +00:00
if isinstance(attributed_to, str) and content:
actor = attributed_to
name_str += ' ' + translate['announces'] + ' ' + \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(actor)
2022-01-02 12:23:59 +00:00
say_str = name_str
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
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)
2022-01-02 12:23:59 +00:00
message_str, _ = \
2021-12-29 21:55:09 +00:00
speakable_text(base_dir, content, translate)
2022-01-02 12:23:59 +00:00
say_str = content
_say_command(say_str, message_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-12-25 22:09:19 +00:00
return post_json_object2
return {}
2022-01-02 12:23:59 +00:00
attributed_to = post_json_object['object']['attributedTo']
if not attributed_to:
2021-07-09 20:00:02 +00:00
return {}
2021-12-26 11:29:40 +00:00
content = get_base_content_from_post(post_json_object, system_language)
2022-01-02 12:23:59 +00:00
if not isinstance(attributed_to, str) or \
2021-07-09 20:00:02 +00:00
not isinstance(content, str):
return {}
2022-01-02 12:23:59 +00:00
actor = attributed_to
name_str = 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):
2022-01-02 12:23:59 +00:00
say_str = 'Encrypted message. Please enter your passphrase.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-12-29 21:55:09 +00:00
content = pgp_decrypt(domain, content, actor, signing_priv_key_pem)
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
2022-01-02 12:23:59 +00:00
say_str = 'Message could not be decrypted'
_say_command(say_str, say_str,
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)
2022-01-02 12:23:59 +00:00
message_str, _ = 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
2022-01-02 12:23:59 +00:00
_say_command(name_str, name_str, screenreader,
system_language, espeak, name_str, 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
2022-01-02 12:23:59 +00:00
_say_command(content, message_str, screenreader,
system_language, espeak, name_str, 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
2022-01-02 12:23:59 +00:00
if _post_is_to_you(your_actor, post_json_object):
2021-12-26 20:12:18 +00:00
if is_dm(post_json_object):
2022-01-02 12:23:59 +00:00
_mark_post_as_read(your_actor, post_json_object['id'], 'dm')
else:
2022-01-02 12:23:59 +00:00
_mark_post_as_read(your_actor, 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']
2022-01-02 12:23:59 +00:00
actor_nickname = get_nickname_from_actor(actor)
actor_domain, actor_port = get_domain_from_actor(actor)
actor_domain_full = get_full_domain(actor_domain, actor_port)
handle = '@' + actor_nickname + '@' + actor_domain_full
2021-03-25 12:39:10 +00:00
2022-01-02 12:23:59 +00:00
say_str = 'Profile for ' + html.unescape(handle)
_say_command(say_str, say_str, 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'):
2022-01-02 12:23:59 +00:00
say_str = 'Moved to ' + html.unescape(actor_json['movedTo'])
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-12-26 10:29:52 +00:00
if actor_json.get('alsoKnownAs'):
2022-01-02 12:23:59 +00:00
also_known_as_str = ''
2021-03-25 12:39:10 +00:00
ctr = 0
2022-01-02 12:23:59 +00:00
for alt_actor in actor_json['alsoKnownAs']:
2021-03-25 12:39:10 +00:00
if ctr > 0:
2022-01-02 12:23:59 +00:00
also_known_as_str += ', '
2021-03-25 12:39:10 +00:00
ctr += 1
2022-01-02 12:23:59 +00:00
also_known_as_str += alt_actor
2021-03-25 12:39:10 +00:00
2022-01-02 12:23:59 +00:00
say_str = 'Also known as ' + html.unescape(also_known_as_str)
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-12-26 10:29:52 +00:00
if actor_json.get('summary'):
2022-01-02 12:23:59 +00:00
say_str = html.unescape(remove_html(actor_json['summary']))
say_str = say_str.replace('"', "'")
say_str2 = speakable_text(base_dir, say_str, translate)[0]
_say_command(say_str, say_str2, screenreader, system_language, espeak)
2021-12-29 21:55:09 +00:00
def _desktop_show_profile(session, nickname: str, domain: str,
2022-01-02 12:23:59 +00:00
http_prefix: str, base_dir: str, box_name: str,
page_number: int, index: int, box_json: {},
2021-12-29 21:55:09 +00:00
system_language: str,
screenreader: str, espeak,
2022-01-02 12:23:59 +00:00
translate: {}, your_actor: str,
2021-12-29 21:55:09 +00:00
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
"""
2022-01-02 12:23:59 +00:00
if _timeline_is_empty(box_json):
2021-03-22 18:27:48 +00:00
return {}
2021-12-25 22:09:19 +00:00
if not post_json_object:
2022-01-02 12:23:59 +00:00
post_json_object = _desktop_get_box_post_object(box_json, 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:
2022-01-02 12:23:59 +00:00
nick_str = '/' + nickname + '/'
if nick_str in post_json_object['object']:
2021-03-22 18:27:48 +00:00
actor = \
2022-01-02 12:23:59 +00:00
post_json_object['object'].split(nick_str)[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 {}
2022-01-02 12:23:59 +00:00
is_http = False
2021-03-22 18:27:48 +00:00
if 'http://' in actor:
2022-01-02 12:23:59 +00:00
is_http = True
actor_json, _ = \
get_actor_json(domain, actor, is_http, False, False, True,
2021-12-29 21:55:09 +00:00
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,
2022-01-02 12:23:59 +00:00
box_name: str, handle: str,
2021-12-29 21:55:09 +00:00
system_language: str,
screenreader: str, espeak,
2022-01-02 12:23:59 +00:00
translate: {}, your_actor: str,
2021-12-29 21:55:09 +00:00
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
"""
2022-01-02 12:23:59 +00:00
actor_json, _ = \
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
2022-01-02 12:23:59 +00:00
def _desktop_get_box_post_object(box_json: {}, index: int) -> {}:
"""Gets the post with the given index from the timeline
"""
ctr = 0
2022-01-02 12:23:59 +00:00
for post_json_object in box_json['orderedItems']:
2021-12-25 22:09:19 +00:00
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
"""
2022-01-02 12:23:59 +00:00
date_str = published.split('T')[0]
month_str = date_str.split('-')[1]
day_str = date_str.split('-')[2]
time_str = published.split('T')[1]
hour_str = time_str.split(':')[0]
min_str = time_str.split(':')[1]
return month_str + '-' + day_str + ' ' + hour_str + ':' + min_str + 'Z'
2021-03-18 22:16:01 +00:00
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,
2022-01-02 12:23:59 +00:00
follow_requests_json: {},
your_actor: str, box_name: str, box_json: {},
2021-12-29 21:55:09 +00:00
translate: {},
screenreader: str, system_language: str, espeak,
2022-01-02 12:23:59 +00:00
page_number: int,
2021-12-29 21:55:09 +00:00
newReplies: bool,
newDMs: bool) -> bool:
"""Shows online timeline
"""
2022-01-02 12:23:59 +00:00
number_width = 2
name_width = 16
content_width = 50
# title
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2022-01-02 12:23:59 +00:00
notification_icons = ''
if box_name.startswith('tl'):
box_name_str = box_name[2:]
2021-03-19 15:39:16 +00:00
else:
2022-01-02 12:23:59 +00:00
box_name_str = box_name
title_str = _highlight_text(box_name_str.upper())
2021-03-24 17:24:22 +00:00
# if newDMs:
2022-01-02 12:23:59 +00:00
# notification_icons += ' 📩'
2021-03-24 17:24:22 +00:00
# if newReplies:
2022-01-02 12:23:59 +00:00
# notification_icons += ' 📨'
if notification_icons:
while len(title_str) < 95 - len(notification_icons):
title_str += ' '
title_str += notification_icons
print(indent + title_str + '\n')
if _timeline_is_empty(box_json):
box_str = box_name_str
if box_name == 'dm':
box_str = 'DM'
say_str = indent + 'You have no ' + box_str + ' posts yet.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
print('')
return False
ctr = 1
2022-01-02 12:23:59 +00:00
for post_json_object in box_json['orderedItems']:
2021-12-25 22:09:19 +00:00
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):
2022-01-02 12:23:59 +00:00
author_actor = post_json_object['actor']
name = get_nickname_from_actor(author_actor) + ''
name = _pad_to_width(name, name_width)
ctr_str = str(ctr)
pos_str = _pad_to_width(ctr_str, number_width)
2021-12-29 21:55:09 +00:00
published = \
_format_published(post_json_object['published'])
2022-01-02 12:23:59 +00:00
announced_nickname = \
2021-12-27 22:19:18 +00:00
get_nickname_from_actor(post_json_object['object'])
2022-01-02 12:23:59 +00:00
announced_domain, _ = \
2021-12-27 19:05:25 +00:00
get_domain_from_actor(post_json_object['object'])
2022-01-02 12:23:59 +00:00
announced_handle = \
announced_nickname + '@' + announced_domain
line_str = \
indent + str(pos_str) + ' | ' + name + ' | ' + \
2021-03-23 11:22:09 +00:00
published + ' | ' + \
2022-01-02 12:23:59 +00:00
_pad_to_width(announced_handle, content_width)
print(line_str)
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
2022-01-02 12:23:59 +00:00
ctr_str = str(ctr)
pos_str = _pad_to_width(ctr_str, number_width)
2022-01-02 12:23:59 +00:00
author_actor = post_json_object['object']['attributedTo']
content_warning = None
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('summary'):
2022-01-02 12:23:59 +00:00
content_warning = '' + \
2021-12-29 21:55:09 +00:00
_pad_to_width(post_json_object['object']['summary'],
2022-01-02 12:23:59 +00:00
content_width)
name = get_nickname_from_actor(author_actor)
# append icons to the end of the name
2022-01-02 12:23:59 +00:00
space_added = False
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('inReplyTo'):
2022-01-02 12:23:59 +00:00
if not space_added:
space_added = True
2021-03-18 20:11:28 +00:00
name += ' '
name += ''
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('replies'):
2022-01-02 12:23:59 +00:00
replies_list = post_json_object['object']['replies']
if replies_list.get('items'):
items = replies_list['items']
2021-03-23 19:14:49 +00:00
for i in range(int(items)):
name += ''
if i > 10:
break
2022-01-02 12:23:59 +00:00
likes_count = no_of_likes(post_json_object)
if likes_count > 10:
likes_count = 10
for _ in range(likes_count):
if not space_added:
space_added = True
2021-03-18 20:11:28 +00:00
name += ' '
2021-03-18 20:04:49 +00:00
name += ''
2022-01-02 12:23:59 +00:00
name = _pad_to_width(name, name_width)
2021-12-29 21:55:09 +00:00
published = _format_published(post_json_object['published'])
2022-01-02 12:23:59 +00:00
content_str = get_base_content_from_post(post_json_object,
system_language)
content = _text_only_content(content_str)
if box_name != 'dm':
2021-12-26 20:12:18 +00:00
if is_dm(post_json_object):
content = '📧' + content
2022-01-02 12:23:59 +00:00
if not content_warning:
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
content = '🔒' + content
elif '://' in content:
content = '🔗' + content
2022-01-02 12:23:59 +00:00
content = _pad_to_width(content, content_width)
else:
# display content warning
2021-12-26 19:15:36 +00:00
if is_pgp_encrypted(content):
2022-01-02 12:23:59 +00:00
content = '🔒' + content_warning
else:
if '://' in content:
2022-01-02 12:23:59 +00:00
content = '🔗' + content_warning
else:
2022-01-02 12:23:59 +00:00
content = content_warning
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', ' ')
2022-01-02 12:23:59 +00:00
line_str = indent + str(pos_str) + ' | ' + name + ' | ' + \
2021-03-23 11:22:09 +00:00
published + ' | ' + content
2022-01-02 12:23:59 +00:00
if box_name == 'inbox' and \
_post_is_to_you(your_actor, post_json_object):
if not _has_read_post(your_actor, post_json_object['id'], 'dm'):
if not _has_read_post(your_actor, post_json_object['id'],
2021-12-29 21:55:09 +00:00
'replies'):
2022-01-02 12:23:59 +00:00
line_str = _highlight_text(line_str)
print(line_str)
ctr += 1
2022-01-02 12:23:59 +00:00
if follow_requests_json:
_desktop_show_follow_requests(follow_requests_json, translate)
print('')
# say the post number range
2022-01-02 12:23:59 +00:00
say_str = indent + box_name_str + ' page ' + str(page_number) + \
' containing ' + str(ctr - 1) + ' posts. '
2022-01-02 12:23:59 +00:00
say_str2 = say_str.replace('\33[3m', '').replace('\33[0m', '')
say_str2 = say_str2.replace('show dm', 'show DM')
say_str2 = say_str2.replace('dm post', 'Direct message post')
_say_command(say_str, say_str2, screenreader, system_language, espeak)
print('')
return True
2022-01-02 12:23:59 +00:00
def _desktop_new_dm(session, to_handle: str,
2021-12-29 21:55:09 +00:00
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,
languages_understood: [],
2021-12-29 21:55:09 +00:00
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
"""
2022-01-02 12:23:59 +00:00
if ' ' in to_handle:
handles_list = to_handle.split(' ')
elif ',' in to_handle:
handles_list = to_handle.split(',')
elif ';' in to_handle:
handles_list = to_handle.split(';')
2021-03-14 10:28:48 +00:00
else:
2022-01-02 12:23:59 +00:00
handles_list = [to_handle]
2021-03-14 10:28:48 +00:00
2022-01-02 12:23:59 +00:00
for handle in handles_list:
2021-03-14 10:28:48 +00:00
handle = handle.strip()
_desktop_new_dm_base(session, handle,
2021-12-29 21:55:09 +00:00
base_dir, nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug,
screenreader, system_language,
languages_understood,
2021-12-29 21:55:09 +00:00
espeak, low_bandwidth,
content_license_url,
signing_priv_key_pem)
def _desktop_new_dm_base(session, to_handle: str,
2021-12-29 21:55:09 +00:00
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,
languages_understood: [],
2021-12-29 21:55:09 +00:00
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
"""
2022-01-02 12:23:59 +00:00
conversation_id = None
to_port = port
if '://' in to_handle:
to_nickname = get_nickname_from_actor(to_handle)
to_domain, to_port = get_domain_from_actor(to_handle)
to_handle = to_nickname + '@' + to_domain
2021-03-11 12:24:20 +00:00
else:
2022-01-02 12:23:59 +00:00
if to_handle.startswith('@'):
to_handle = to_handle[1:]
to_nickname = to_handle.split('@')[0]
to_domain = to_handle.split('@')[1]
say_str = 'Create new direct message to ' + to_handle
_say_command(say_str, say_str, screenreader, system_language, espeak)
say_str = 'Type your direct message, then press Enter.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
new_message = input()
if not new_message:
say_str = 'No direct message was entered.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
return
2022-01-02 12:23:59 +00:00
new_message = new_message.strip()
if not new_message:
say_str = 'No direct message was entered.'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
return
2022-01-02 12:23:59 +00:00
say_str = 'You entered this direct message to ' + to_handle + ':'
_say_command(say_str, say_str, screenreader, system_language, espeak)
_say_command(new_message, new_message,
screenreader, system_language, espeak)
cc_url = None
followers_only = False
2021-03-11 12:24:20 +00:00
attach = None
2022-01-02 12:23:59 +00:00
media_type = None
attached_image_description = None
2021-05-09 19:29:53 +00:00
city = 'London, England'
2022-01-02 12:23:59 +00:00
is_article = False
2021-03-11 12:24:20 +00:00
subject = None
2022-01-02 12:23:59 +00:00
comments_enabled = True
2021-03-11 12:24:20 +00:00
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():
2022-01-02 12:23:59 +00:00
say_str = \
'Local PGP key detected...' + \
2022-01-02 12:23:59 +00:00
'Fetching PGP public key for ' + to_handle
_say_command(say_str, say_str, screenreader, system_language, espeak)
padded_message = new_message
if len(padded_message) < 32:
# add some padding before and after
# This is to guard against cribs based on small messages, like "Hi"
2022-01-02 12:23:59 +00:00
for _ in range(randint(1, 16)):
padded_message = ' ' + padded_message
for _ in range(randint(1, 16)):
padded_message += ' '
cipher_text = \
pgp_encrypt_to_actor(domain, padded_message, to_handle,
2021-12-29 21:55:09 +00:00
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
if not cipher_text:
say_str = \
to_handle + ' has no PGP public key. ' + \
'Your message will be sent in clear text'
2022-01-02 12:23:59 +00:00
_say_command(say_str, say_str,
screenreader, system_language, espeak)
else:
2022-01-02 12:23:59 +00:00
new_message = cipher_text
say_str = 'Message encrypted'
_say_command(say_str, say_str,
screenreader, system_language, espeak)
2022-01-02 12:23:59 +00:00
say_str = 'Send this direct message, yes or no?'
_say_command(say_str, say_str, screenreader, system_language, espeak)
yesno = input()
if 'y' not in yesno.lower():
2022-01-02 12:23:59 +00:00
say_str = 'Abandoning new direct message'
_say_command(say_str, say_str, screenreader, system_language, espeak)
return
event_date = None
event_time = None
location = None
2022-01-02 12:23:59 +00:00
say_str = 'Sending'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-12-29 21:55:09 +00:00
if send_post_via_server(signing_priv_key_pem, __version__,
base_dir, session, nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
to_nickname, to_domain, to_port, cc_url,
http_prefix, new_message, followers_only,
comments_enabled, attach, media_type,
attached_image_description, city,
cached_webfingers, person_cache, is_article,
system_language, languages_understood,
low_bandwidth, content_license_url,
event_date, event_time, location,
2021-12-29 21:55:09 +00:00
debug, None, None,
2022-01-02 12:23:59 +00:00
conversation_id, subject) == 0:
say_str = 'Direct message sent'
2021-03-11 12:24:20 +00:00
else:
2022-01-02 12:23:59 +00:00
say_str = 'Direct message failed'
_say_command(say_str, say_str, screenreader, system_language, espeak)
2021-03-11 12:24:20 +00:00
2022-01-02 12:23:59 +00:00
def _desktop_show_follow_requests(follow_requests_json: {},
2021-12-29 21:55:09 +00:00
translate: {}) -> None:
"""Shows any follow requests
"""
2022-01-02 12:23:59 +00:00
if not isinstance(follow_requests_json, dict):
2021-03-25 10:56:41 +00:00
return
2022-01-02 12:23:59 +00:00
if not follow_requests_json.get('orderedItems'):
2021-03-25 10:56:41 +00:00
return
2022-01-02 12:23:59 +00:00
if not follow_requests_json['orderedItems']:
return
indent = ' '
print('')
print(indent + 'Follow requests:')
print('')
2022-01-02 12:23:59 +00:00
for item in follow_requests_json['orderedItems']:
handle_nickname = get_nickname_from_actor(item)
handle_domain, handle_port = get_domain_from_actor(item)
handle_domain_full = \
get_full_domain(handle_domain, handle_port)
print(indent + ' 👤 ' +
2022-01-02 12:23:59 +00:00
handle_nickname + '@' + handle_domain_full)
2022-01-02 12:23:59 +00:00
def _desktop_show_following(following_json: {}, translate: {},
page_number: int, indent: str,
2021-12-29 21:55:09 +00:00
followType='following') -> None:
"""Shows a page of accounts followed
"""
2022-01-02 12:23:59 +00:00
if not isinstance(following_json, dict):
2021-03-25 10:58:53 +00:00
return
2022-01-02 12:23:59 +00:00
if not following_json.get('orderedItems'):
2021-03-25 10:58:53 +00:00
return
2022-01-02 12:23:59 +00:00
if not following_json['orderedItems']:
return
print('')
if followType == 'following':
2022-01-02 12:23:59 +00:00
print(indent + 'Following page ' + str(page_number))
elif followType == 'followers':
2022-01-02 12:23:59 +00:00
print(indent + 'Followers page ' + str(page_number))
print('')
2022-01-02 12:23:59 +00:00
for item in following_json['orderedItems']:
handle_nickname = get_nickname_from_actor(item)
handle_domain, handle_port = get_domain_from_actor(item)
handle_domain_full = \
get_full_domain(handle_domain, handle_port)
print(indent + ' 👤 ' +
2022-01-02 12:23:59 +00:00
handle_nickname + '@' + handle_domain_full)
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,
2022-01-02 12:23:59 +00:00
notification_sounds: bool,
notification_type: str,
no_key_press: bool,
store_inbox_posts: bool,
show_new_posts: bool,
2021-12-29 21:55:09 +00:00
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
"""
2022-03-24 14:40:28 +00:00
bold_reading = False
# 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
2021-12-31 23:07:23 +00:00
blocked_cache = {}
languages_understood = []
2021-03-15 14:30:59 +00:00
indent = ' '
2022-01-02 12:23:59 +00:00
if show_new_posts:
2021-03-15 13:51:21 +00:00
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
2022-01-02 12:23:59 +00:00
say_str = indent + 'Running ' + screenreader + ' for ' + \
2021-03-15 13:51:21 +00:00
nickname + '@' + domain
2022-01-02 12:23:59 +00:00
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
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)
2022-01-02 12:23:59 +00:00
if notification_sounds:
say_str = indent + 'Notification sounds on'
else:
2022-01-02 12:23:59 +00:00
say_str = indent + 'Notification sounds off'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-12-26 13:17:46 +00:00
curr_timeline = 'inbox'
2022-01-02 12:23:59 +00:00
page_number = 1
2021-03-10 10:51:06 +00:00
2021-12-25 22:09:19 +00:00
post_json_object = {}
2022-01-02 12:23:59 +00:00
original_screen_reader = screenreader
sounds_dir = 'theme/default/sounds/'
2022-01-04 21:19:06 +00:00
# prev_say = ''
# prev_calendar = False
# prev_follow = False
# prev_like = ''
# prev_share = False
2022-01-02 12:23:59 +00:00
dm_sound_filename = sounds_dir + 'dm.ogg'
reply_sound_filename = sounds_dir + 'reply.ogg'
2022-01-04 21:19:06 +00:00
# calendar_sound_filename = sounds_dir + 'calendar.ogg'
# follow_sound_filename = sounds_dir + 'follow.ogg'
# like_sound_filename = sounds_dir + 'like.ogg'
# share_sound_filename = sounds_dir + 'share.ogg'
2021-03-22 13:43:20 +00:00
player = 'ffplay'
2022-01-02 12:23:59 +00:00
name_str = None
2021-03-10 12:37:44 +00:00
gender = None
2022-01-02 12:23:59 +00:00
message_str = 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 = {}
2022-01-02 12:23:59 +00:00
new_replies_exist = False
new_dms_exist = False
pgp_key_upload = False
2021-03-17 20:18:00 +00:00
2022-01-02 12:23:59 +00:00
say_str = indent + 'Loading translations file'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
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
2022-01-02 12:23:59 +00:00
say_str = indent + 'Connecting...'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-12-28 16:56:57 +00:00
session = create_session(proxy_type)
2021-03-18 17:30:47 +00:00
2022-01-02 12:23:59 +00:00
say_str = indent + '/q or /quit to exit'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-12-26 12:45:03 +00:00
domain_full = get_full_domain(domain, port)
2022-01-02 12:23:59 +00:00
your_actor = local_actor_url(http_prefix, nickname, domain_full)
2021-12-26 10:29:52 +00:00
actor_json = None
2022-01-02 12:23:59 +00:00
notify_json = {
2021-03-22 13:43:20 +00:00
"dmPostId": "Initial",
"dmNotify": False,
"dmNotifyChanged": False,
"repliesPostId": "Initial",
"repliesNotify": False,
"repliesNotifyChanged": False
}
2022-01-02 12:23:59 +00:00
prev_timeline_first_id = ''
desktop_shown = False
while (1):
2022-01-02 12:23:59 +00:00
if not pgp_key_upload:
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:
2022-01-02 12:23:59 +00:00
say_str = indent + 'Uploading PGP public key'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
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)
2022-01-02 12:23:59 +00:00
say_str = indent + 'PGP public key uploaded'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2022-01-02 12:23:59 +00:00
pgp_key_upload = True
2021-03-17 20:18:00 +00:00
2022-01-02 12:23:59 +00:00
box_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, page_number,
debug, signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
follow_requests_json = \
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)
2022-01-02 12:23:59 +00:00
if not (curr_timeline == 'inbox' and page_number == 1):
# monitor the inbox to generate notifications
2022-01-02 12:23:59 +00:00
inbox_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
'inbox', 1, debug,
signing_priv_key_pem)
else:
2022-01-02 12:23:59 +00:00
inbox_json = box_json
new_dms_exist = False
new_replies_exist = False
if inbox_json:
_new_desktop_notifications(your_actor, inbox_json, notify_json)
if notify_json.get('dmNotify'):
new_dms_exist = True
if notify_json.get('dmNotifyChanged'):
_desktop_notification(notification_type,
2021-12-29 21:55:09 +00:00
"Epicyon",
2022-01-02 12:23:59 +00:00
"New DM " + your_actor + '/dm')
if notification_sounds:
_play_notification_sound(dm_sound_filename, player)
if notify_json.get('repliesNotify'):
new_replies_exist = True
if notify_json.get('repliesNotifyChanged'):
_desktop_notification(notification_type,
2021-12-29 21:55:09 +00:00
"Epicyon",
"New reply " +
2022-01-02 12:23:59 +00:00
your_actor + '/replies')
if notification_sounds:
_play_notification_sound(reply_sound_filename, player)
2022-01-02 12:23:59 +00:00
if box_json:
timeline_first_id = _get_first_item_id(box_json)
if timeline_first_id != prev_timeline_first_id:
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
2022-01-02 12:23:59 +00:00
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
None, system_language, espeak,
2022-01-02 12:23:59 +00:00
page_number,
new_replies_exist,
new_dms_exist)
desktop_shown = True
prev_timeline_first_id = timeline_first_id
2021-03-19 15:31:16 +00:00
else:
2021-12-28 16:56:57 +00:00
session = create_session(proxy_type)
2022-01-02 12:23:59 +00:00
if not desktop_shown:
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
2022-01-02 12:23:59 +00:00
if no_key_press:
time.sleep(10)
else:
2022-01-02 12:23:59 +00:00
command_str = _desktop_wait_for_cmd(30, debug)
if command_str:
refresh_timeline = False
if command_str.startswith('/'):
command_str = command_str[1:]
if command_str in ('q', 'quit', 'exit'):
say_str = 'Quit'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-03-10 18:31:45 +00:00
if screenreader:
2022-01-02 12:23:59 +00:00
command_str = _desktop_wait_for_cmd(2, debug)
2021-03-04 18:05:46 +00:00
break
2022-01-02 12:23:59 +00:00
if command_str.startswith('show dm'):
page_number = 1
prev_timeline_first_id = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'dm'
2022-01-02 12:23:59 +00:00
box_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, page_number,
debug, signing_priv_key_pem)
if box_json:
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
screenreader, system_language, espeak,
2022-01-02 12:23:59 +00:00
page_number,
new_replies_exist, new_dms_exist)
new_dms_exist = False
elif command_str.startswith('show rep'):
page_number = 1
prev_timeline_first_id = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'tlreplies'
2022-01-02 12:23:59 +00:00
box_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, page_number,
debug, signing_priv_key_pem)
if box_json:
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
screenreader, system_language, espeak,
2022-01-02 12:23:59 +00:00
page_number,
new_replies_exist, new_dms_exist)
# Turn off the replies indicator
2022-01-02 12:23:59 +00:00
new_replies_exist = False
elif command_str.startswith('show b'):
page_number = 1
prev_timeline_first_id = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'tlbookmarks'
2022-01-02 12:23:59 +00:00
box_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, page_number,
debug, signing_priv_key_pem)
if box_json:
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
screenreader, system_language, espeak,
2022-01-02 12:23:59 +00:00
page_number,
new_replies_exist, new_dms_exist)
2021-03-19 21:34:38 +00:00
# Turn off the replies indicator
2022-01-02 12:23:59 +00:00
new_replies_exist = False
elif (command_str.startswith('show sen') or
command_str.startswith('show out')):
page_number = 1
prev_timeline_first_id = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'outbox'
2022-01-02 12:23:59 +00:00
box_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, page_number,
debug, signing_priv_key_pem)
if box_json:
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
screenreader, system_language, espeak,
2022-01-02 12:23:59 +00:00
page_number,
new_replies_exist, new_dms_exist)
elif (command_str == 'show' or command_str.startswith('show in') or
command_str == 'clear'):
page_number = 1
prev_timeline_first_id = ''
2021-12-26 13:17:46 +00:00
curr_timeline = 'inbox'
2022-01-02 12:23:59 +00:00
refresh_timeline = True
elif command_str.startswith('next'):
page_number += 1
prev_timeline_first_id = ''
refresh_timeline = True
elif command_str.startswith('prev'):
page_number -= 1
if page_number < 1:
page_number = 1
prev_timeline_first_id = ''
box_json = c2s_box_json(base_dir, session,
nickname, password,
domain, port, http_prefix,
curr_timeline, page_number,
debug, signing_priv_key_pem)
if box_json:
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
screenreader, system_language, espeak,
2022-01-02 12:23:59 +00:00
page_number,
new_replies_exist, new_dms_exist)
elif command_str.startswith('read ') or command_str == 'read':
if command_str == 'read':
post_index_str = '1'
2021-03-16 14:06:05 +00:00
else:
2022-01-02 12:23:59 +00:00
post_index_str = command_str.split('read ')[1]
if box_json and post_index_str.isdigit():
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2022-01-02 12:23:59 +00:00
post_index = int(post_index_str)
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,
2022-01-02 12:23:59 +00:00
page_number, post_index, box_json,
2021-12-29 21:55:09 +00:00
system_language, screenreader,
2022-01-02 12:23:59 +00:00
espeak, translate, your_actor,
2021-12-29 21:55:09 +00:00
domain_full, person_cache,
signing_priv_key_pem,
2022-03-24 14:40:28 +00:00
blocked_cache, bold_reading)
2021-03-25 10:56:41 +00:00
print('')
2022-01-02 12:23:59 +00:00
say_str = 'Press Enter to continue...'
say_str2 = _highlight_text(say_str)
_say_command(say_str2, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
input()
2022-01-02 12:23:59 +00:00
prev_timeline_first_id = ''
refresh_timeline = True
2021-03-12 19:55:16 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif (command_str.startswith('profile ') or
command_str == 'profile'):
2021-12-26 10:29:52 +00:00
actor_json = None
2022-01-02 12:23:59 +00:00
if command_str == '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,
2022-01-02 12:23:59 +00:00
page_number, post_index,
box_json,
2021-12-29 21:55:09 +00:00
system_language,
screenreader,
2022-01-02 12:23:59 +00:00
espeak, translate,
your_actor,
2021-12-29 21:55:09 +00:00
post_json_object,
signing_priv_key_pem)
2021-03-23 16:17:03 +00:00
else:
2022-01-02 12:23:59 +00:00
post_index_str = '1'
2021-03-22 18:27:48 +00:00
else:
2022-01-02 12:23:59 +00:00
post_index_str = command_str.split('profile ')[1]
2021-03-23 16:17:03 +00:00
2022-01-02 12:23:59 +00:00
if not post_index_str.isdigit():
profile_handle = post_index_str
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,
2022-01-02 12:23:59 +00:00
profile_handle,
2021-12-29 21:55:09 +00:00
system_language,
screenreader,
espeak, translate,
2022-01-02 12:23:59 +00:00
your_actor,
2021-12-29 21:55:09 +00:00
None,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
say_str = 'Press Enter to continue...'
say_str2 = _highlight_text(say_str)
_say_command(say_str2, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2021-03-25 14:15:36 +00:00
input()
2022-01-02 12:23:59 +00:00
prev_timeline_first_id = ''
refresh_timeline = True
elif not actor_json and box_json:
2021-12-29 21:55:09 +00:00
_desktop_clear_screen()
_desktop_show_banner()
2022-01-02 12:23:59 +00:00
post_index = int(post_index_str)
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,
2022-01-02 12:23:59 +00:00
page_number, post_index,
box_json,
2021-12-29 21:55:09 +00:00
system_language, screenreader,
2022-01-02 12:23:59 +00:00
espeak, translate, your_actor,
2021-12-29 21:55:09 +00:00
None, signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
say_str = 'Press Enter to continue...'
say_str2 = _highlight_text(say_str)
_say_command(say_str2, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2021-03-25 14:15:36 +00:00
input()
2022-01-02 12:23:59 +00:00
prev_timeline_first_id = ''
refresh_timeline = True
2021-03-22 18:27:48 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif command_str in ('reply', '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']
2022-01-02 12:23:59 +00:00
conversation_id = None
2021-12-25 22:09:19 +00:00
if post_json_object['object'].get('conversation'):
2022-01-02 12:23:59 +00:00
conversation_id = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['conversation']
2022-01-02 12:23:59 +00:00
session_reply = create_session(proxy_type)
_desktop_reply_to_post(session_reply, post_id,
2021-12-29 21:55:09 +00:00
base_dir, nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug, subject,
screenreader, system_language,
languages_understood,
2022-01-02 12:23:59 +00:00
espeak, conversation_id,
2021-12-29 21:55:09 +00:00
low_bandwidth,
content_license_url,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'post' or command_str == 'p' or
command_str == 'send' or
command_str.startswith('dm ') or
command_str.startswith('direct message ') or
command_str.startswith('post ') or
command_str.startswith('send ')):
session_post = create_session(proxy_type)
if command_str.startswith('dm ') or \
command_str.startswith('direct message ') or \
command_str.startswith('post ') or \
command_str.startswith('send '):
command_str = command_str.replace(' to ', ' ')
command_str = command_str.replace(' dm ', ' ')
command_str = command_str.replace(' DM ', ' ')
2021-03-11 12:24:20 +00:00
# direct message
2022-01-02 12:23:59 +00:00
to_handle = None
if command_str.startswith('post '):
to_handle = command_str.split('post ', 1)[1]
elif command_str.startswith('send '):
to_handle = command_str.split('send ', 1)[1]
elif command_str.startswith('dm '):
to_handle = command_str.split('dm ', 1)[1]
elif command_str.startswith('direct message '):
to_handle = command_str.split('direct message ', 1)[1]
if to_handle:
_desktop_new_dm(session_post, to_handle,
2021-12-29 21:55:09 +00:00
base_dir, nickname, password,
domain, port, http_prefix,
cached_webfingers, person_cache,
debug,
screenreader, system_language,
languages_understood,
2021-12-29 21:55:09 +00:00
espeak, low_bandwidth,
content_license_url,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-12-29 21:55:09 +00:00
else:
# public post
2022-01-02 12:23:59 +00:00
_desktop_new_post(session_post,
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,
languages_understood,
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)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-10 18:30:00 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif command_str == 'like' or command_str.startswith('like '):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
like_actor = post_json_object['object']['attributedTo']
say_str = 'Liking post by ' + \
get_nickname_from_actor(like_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_like = create_session(proxy_type)
send_like_via_server(base_dir, session_like,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port, http_prefix,
post_json_object['id'],
cached_webfingers, person_cache,
False, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'undo mute' or
command_str == 'undo ignore' or
command_str == 'remove mute' or
command_str == 'rm mute' or
command_str == 'unmute' or
command_str == 'unignore' or
command_str == 'mute undo' or
command_str.startswith('undo mute ') or
command_str.startswith('undo ignore ') or
command_str.startswith('remove mute ') or
command_str.startswith('remove ignore ') or
command_str.startswith('unignore ') or
command_str.startswith('unmute ')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
mute_actor = post_json_object['object']['attributedTo']
say_str = 'Unmuting post by ' + \
get_nickname_from_actor(mute_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_mute = create_session(proxy_type)
send_undo_mute_via_server(base_dir, session_mute,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-21 12:31:48 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'mute' or
command_str == 'ignore' or
command_str.startswith('mute ') or
command_str.startswith('ignore ')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
mute_actor = post_json_object['object']['attributedTo']
say_str = 'Muting post by ' + \
get_nickname_from_actor(mute_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_mute = create_session(proxy_type)
send_mute_via_server(base_dir, session_mute,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix,
post_json_object['id'],
cached_webfingers, person_cache,
False, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-21 12:31:48 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'undo bookmark' or
command_str == 'remove bookmark' or
command_str == 'rm bookmark' or
command_str == 'undo bm' or
command_str == 'rm bm' or
command_str == 'remove bm' or
command_str == 'unbookmark' or
command_str == 'bookmark undo' or
command_str == 'bm undo ' or
command_str.startswith('undo bm ') or
command_str.startswith('remove bm ') or
command_str.startswith('undo bookmark ') or
command_str.startswith('remove bookmark ') or
command_str.startswith('unbookmark ') or
command_str.startswith('unbm ')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
bm_actor = post_json_object['object']['attributedTo']
say_str = 'Unbookmarking post by ' + \
get_nickname_from_actor(bm_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
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)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-19 22:04:57 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'bookmark' or
command_str == 'bm' or
command_str.startswith('bookmark ') or
command_str.startswith('bm ')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
bm_actor = post_json_object['object']['attributedTo']
say_str = 'Bookmarking post by ' + \
get_nickname_from_actor(bm_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
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)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-19 22:11:45 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif (command_str.startswith('undo block ') or
command_str.startswith('remove block ') or
command_str.startswith('rm block ') or
command_str.startswith('unblock ')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
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'):
2022-01-02 12:23:59 +00:00
block_actor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2022-01-02 12:23:59 +00:00
say_str = 'Unblocking ' + \
get_nickname_from_actor(block_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_block = 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,
2022-01-02 12:23:59 +00:00
session_block,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix,
2022-01-02 12:23:59 +00:00
block_actor,
2021-12-29 21:55:09 +00:00
cached_webfingers,
person_cache,
False, __version__,
sign_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-23 14:16:44 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif command_str.startswith('block '):
block_actor = None
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
2021-03-23 14:16:44 +00:00
else:
2022-01-02 12:23:59 +00:00
if '@' in post_index:
block_handle = post_index
if block_handle.startswith('@'):
block_handle = block_handle[1:]
if '@' in block_handle:
block_domain = block_handle.split('@')[1]
block_nickname = block_handle.split('@')[0]
block_actor = \
2021-12-26 10:19:59 +00:00
local_actor_url(http_prefix,
2022-01-02 12:23:59 +00:00
block_nickname,
block_domain)
if curr_index > 0 and box_json and not block_actor:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
if post_json_object and not block_actor:
2021-12-25 22:09:19 +00:00
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'):
2022-01-02 12:23:59 +00:00
block_actor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2022-01-02 12:23:59 +00:00
if block_actor:
say_str = 'Blocking ' + \
get_nickname_from_actor(block_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_block = create_session(proxy_type)
send_block_via_server(base_dir, session_block,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix,
2022-01-02 12:23:59 +00:00
block_actor,
2021-12-29 21:55:09 +00:00
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-23 14:16:44 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif command_str in ('unlike', 'undo like'):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
unlike_actor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2022-01-02 12:23:59 +00:00
say_str = \
'Undoing like of post by ' + \
2022-01-02 12:23:59 +00:00
get_nickname_from_actor(unlike_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_unlike = create_session(proxy_type)
send_undo_like_via_server(base_dir, session_unlike,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port, http_prefix,
post_json_object['id'],
cached_webfingers,
person_cache,
False, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
print('')
2022-01-02 12:23:59 +00:00
elif (command_str.startswith('announce') or
command_str.startswith('boost') or
command_str.startswith('retweet')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
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']
2022-01-02 12:23:59 +00:00
announce_actor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2022-01-02 12:23:59 +00:00
say_str = 'Announcing post by ' + \
get_nickname_from_actor(announce_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_announce = create_session(proxy_type)
send_announce_via_server(base_dir, session_announce,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix, post_id,
cached_webfingers,
person_cache,
True, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
print('')
2022-01-02 12:23:59 +00:00
elif (command_str.startswith('unannounce') or
command_str.startswith('undo announce') or
command_str.startswith('unboost') or
command_str.startswith('undo boost') or
command_str.startswith('undo retweet')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
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']
2022-01-02 12:23:59 +00:00
announce_actor = \
2021-12-25 22:09:19 +00:00
post_json_object['object']['attributedTo']
2022-01-02 12:23:59 +00:00
say_str = 'Undoing announce post by ' + \
get_nickname_from_actor(announce_actor)
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader,
system_language, espeak)
2022-01-02 12:23:59 +00:00
session_announce = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_undo_announce_via_server(base_dir,
2022-01-02 12:23:59 +00:00
session_announce,
2021-12-29 21:55:09 +00:00
post_json_object,
nickname, password,
domain, port,
http_prefix, post_id,
cached_webfingers,
person_cache,
True, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-18 20:56:08 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'follow requests' or
command_str.startswith('follow requests ')):
curr_page = 1
if ' ' in command_str:
page_num = command_str.split(' ')[-1].strip()
if page_num.isdigit():
curr_page = int(page_num)
follow_requests_json = \
2021-12-29 21:55:09 +00:00
get_follow_requests_via_server(base_dir, session,
nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
http_prefix, curr_page,
2021-12-29 21:55:09 +00:00
cached_webfingers,
person_cache,
debug, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
if follow_requests_json:
if isinstance(follow_requests_json, dict):
_desktop_show_follow_requests(follow_requests_json,
2021-12-29 21:55:09 +00:00
translate)
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'following' or
command_str.startswith('following ')):
curr_page = 1
if ' ' in command_str:
page_num = command_str.split(' ')[-1].strip()
if page_num.isdigit():
curr_page = int(page_num)
following_json = \
2021-12-29 21:55:09 +00:00
get_following_via_server(base_dir, session,
nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
http_prefix, curr_page,
2021-12-29 21:55:09 +00:00
cached_webfingers, person_cache,
debug, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
if following_json:
if isinstance(following_json, dict):
_desktop_show_following(following_json, translate,
curr_page, indent,
2021-12-29 21:55:09 +00:00
'following')
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'followers' or
command_str.startswith('followers ')):
curr_page = 1
if ' ' in command_str:
page_num = command_str.split(' ')[-1].strip()
if page_num.isdigit():
curr_page = int(page_num)
followers_json = \
2021-12-29 21:55:09 +00:00
get_followers_via_server(base_dir, session,
nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
http_prefix, curr_page,
2021-12-29 21:55:09 +00:00
cached_webfingers, person_cache,
debug, __version__,
signing_priv_key_pem)
2022-01-02 12:23:59 +00:00
if followers_json:
if isinstance(followers_json, dict):
_desktop_show_following(followers_json, translate,
curr_page, indent,
2021-12-29 21:55:09 +00:00
'followers')
print('')
2022-01-02 12:23:59 +00:00
elif (command_str == 'follow' or
command_str.startswith('follow ')):
if command_str == 'follow':
2021-12-26 10:29:52 +00:00
if actor_json:
2022-01-02 12:23:59 +00:00
follow_handle = actor_json['id']
2021-03-22 18:27:48 +00:00
else:
2022-01-02 12:23:59 +00:00
follow_handle = ''
2021-03-22 18:27:48 +00:00
else:
2022-01-02 12:23:59 +00:00
follow_handle = command_str.replace('follow ', '').strip()
if follow_handle.startswith('@'):
follow_handle = follow_handle[1:]
if '@' in follow_handle or '://' in follow_handle:
follow_nickname = get_nickname_from_actor(follow_handle)
follow_domain, follow_port = \
get_domain_from_actor(follow_handle)
if follow_nickname and follow_domain:
say_str = 'Sending follow request to ' + \
follow_nickname + '@' + follow_domain
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2022-01-02 12:23:59 +00:00
session_follow = create_session(proxy_type)
2022-03-13 12:15:52 +00:00
send_follow_request_via_server(base_dir,
session_follow,
nickname, password,
domain, port,
follow_nickname,
follow_domain,
follow_port,
http_prefix,
cached_webfingers,
person_cache,
debug, __version__,
signing_priv_key_pem)
else:
2022-01-02 12:23:59 +00:00
if follow_handle:
say_str = follow_handle + ' is not valid'
2021-03-22 18:27:48 +00:00
else:
2022-01-02 12:23:59 +00:00
say_str = 'Specify a handle to follow'
_say_command(say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
print('')
2022-01-02 12:23:59 +00:00
elif (command_str.startswith('unfollow ') or
command_str.startswith('stop following ')):
follow_handle = command_str.replace('unfollow ', '').strip()
follow_handle = follow_handle.replace('stop following ', '')
if follow_handle.startswith('@'):
follow_handle = follow_handle[1:]
if '@' in follow_handle or '://' in follow_handle:
follow_nickname = get_nickname_from_actor(follow_handle)
follow_domain, follow_port = \
get_domain_from_actor(follow_handle)
if follow_nickname and follow_domain:
say_str = 'Stop following ' + \
follow_nickname + '@' + follow_domain
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2022-01-02 12:23:59 +00:00
session_unfollow = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
send_unfollow_request_via_server(base_dir,
2022-01-02 12:23:59 +00:00
session_unfollow,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
2022-01-02 12:23:59 +00:00
follow_nickname,
follow_domain,
follow_port,
2021-12-29 21:55:09 +00:00
http_prefix,
cached_webfingers,
person_cache,
debug, __version__,
signing_priv_key_pem)
else:
2022-01-02 12:23:59 +00:00
say_str = follow_handle + ' is not valid'
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
print('')
2022-01-02 12:23:59 +00:00
elif command_str.startswith('approve '):
approve_handle = command_str.replace('approve ', '').strip()
if approve_handle.startswith('@'):
approve_handle = approve_handle[1:]
if '@' in approve_handle or '://' in approve_handle:
approve_nickname = get_nickname_from_actor(approve_handle)
approve_domain, _ = \
get_domain_from_actor(approve_handle)
if approve_nickname and approve_domain:
say_str = 'Sending approve follow request for ' + \
approve_nickname + '@' + approve_domain
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2022-01-02 12:23:59 +00:00
session_approve = create_session(proxy_type)
2021-12-29 21:55:09 +00:00
approve_follow_request_via_server(base_dir,
2022-01-02 12:23:59 +00:00
session_approve,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix,
2022-01-02 12:23:59 +00:00
approve_handle,
2021-12-29 21:55:09 +00:00
cached_webfingers,
person_cache,
debug,
__version__,
signing_priv_key_pem)
else:
2022-01-02 12:23:59 +00:00
if approve_handle:
say_str = approve_handle + ' is not valid'
else:
2022-01-02 12:23:59 +00:00
say_str = 'Specify a handle to approve'
_say_command(say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
print('')
2022-01-02 12:23:59 +00:00
elif command_str.startswith('deny '):
deny_handle = command_str.replace('deny ', '').strip()
if deny_handle.startswith('@'):
deny_handle = deny_handle[1:]
if '@' in deny_handle or '://' in deny_handle:
deny_nickname = get_nickname_from_actor(deny_handle)
deny_domain, _ = \
get_domain_from_actor(deny_handle)
if deny_nickname and deny_domain:
say_str = 'Sending deny follow request for ' + \
deny_nickname + '@' + deny_domain
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2022-01-02 12:23:59 +00:00
session_deny = create_session(proxy_type)
deny_follow_request_via_server(base_dir, session_deny,
2021-12-29 21:55:09 +00:00
nickname, password,
domain, port,
http_prefix,
2022-01-02 12:23:59 +00:00
deny_handle,
2021-12-29 21:55:09 +00:00
cached_webfingers,
person_cache,
debug,
__version__,
signing_priv_key_pem)
else:
2022-01-02 12:23:59 +00:00
if deny_handle:
say_str = deny_handle + ' is not valid'
else:
2022-01-02 12:23:59 +00:00
say_str = 'Specify a handle to deny'
_say_command(say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
print('')
2022-01-02 12:23:59 +00:00
elif command_str in ('repeat', 'replay', 'rp',
'again', 'say again'):
if screenreader and name_str and \
gender and message_str and content:
say_str = 'Repeating ' + name_str
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak,
2022-01-02 12:23:59 +00:00
name_str, gender)
2021-03-10 12:37:44 +00:00
time.sleep(2)
2022-01-02 12:23:59 +00:00
_say_command(content, message_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak,
2022-01-02 12:23:59 +00:00
name_str, gender)
2021-03-10 12:40:17 +00:00
print('')
2022-01-02 12:23:59 +00:00
elif command_str in ('sounds on',
'sound on',
'sound'):
say_str = 'Notification sounds on'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2022-01-02 12:23:59 +00:00
notification_sounds = True
elif command_str in ('sounds off',
'sound off',
'nosound'):
say_str = 'Notification sounds off'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2022-01-02 12:23:59 +00:00
notification_sounds = False
elif command_str in ('speak',
'screen reader on',
'speaker on',
'talker on',
'reader on'):
if original_screen_reader:
screenreader = original_screen_reader
say_str = 'Screen reader on'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-03-10 10:25:41 +00:00
else:
print('No --screenreader option was specified')
2022-01-02 12:23:59 +00:00
elif command_str in ('mute',
'screen reader off',
'speaker off',
'talker off',
'reader off'):
if original_screen_reader:
2021-03-10 10:25:41 +00:00
screenreader = None
2022-01-02 12:23:59 +00:00
say_str = 'Screen reader off'
_say_command(say_str, say_str, original_screen_reader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-03-10 10:25:41 +00:00
else:
print('No --screenreader option was specified')
2022-01-02 12:23:59 +00:00
elif command_str.startswith('open'):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
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,
2022-03-24 14:40:28 +00:00
blocked_cache,
bold_reading)
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)
2022-01-02 12:23:59 +00:00
message_str, detected_links = \
2021-12-29 21:55:09 +00:00
speakable_text(base_dir, content, translate)
2022-01-02 12:23:59 +00:00
link_opened = False
for url in detected_links:
2021-03-18 19:04:58 +00:00
if '://' in url:
webbrowser.open(url)
2022-01-02 12:23:59 +00:00
link_opened = True
if link_opened:
say_str = 'Opened web links'
_say_command(say_str, say_str, original_screen_reader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-03-18 19:04:58 +00:00
else:
2022-01-02 12:23:59 +00:00
say_str = 'There are no web links to open.'
_say_command(say_str, say_str, original_screen_reader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
print('')
2022-01-02 12:23:59 +00:00
elif (command_str.startswith('pgp') or
command_str.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('')
2022-01-02 12:23:59 +00:00
elif command_str.startswith('h'):
2021-12-29 21:55:09 +00:00
_desktop_help()
2022-01-02 12:23:59 +00:00
say_str = 'Press Enter to continue...'
say_str2 = _highlight_text(say_str)
_say_command(say_str2, say_str,
2021-12-29 21:55:09 +00:00
screenreader, system_language, espeak)
2021-03-25 12:21:04 +00:00
input()
2022-01-02 12:23:59 +00:00
prev_timeline_first_id = ''
refresh_timeline = True
elif (command_str == 'delete' or
command_str == 'rm' or
command_str.startswith('delete ') or
command_str.startswith('rm ')):
curr_index = 0
if ' ' in command_str:
post_index = command_str.split(' ')[-1].strip()
if post_index.isdigit():
curr_index = int(post_index)
if curr_index > 0 and box_json:
2021-12-25 22:09:19 +00:00
post_json_object = \
2022-01-02 12:23:59 +00:00
_desktop_get_box_post_object(box_json, curr_index)
2021-12-25 22:09:19 +00:00
if post_json_object:
if post_json_object.get('id'):
2022-01-02 12:23:59 +00:00
rm_actor = post_json_object['object']['attributedTo']
if rm_actor != your_actor:
say_str = 'You can only delete your own posts'
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
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'])
2022-01-02 12:23:59 +00:00
content_str = \
2021-12-26 11:29:40 +00:00
get_base_content_from_post(post_json_object,
system_language)
2022-01-02 12:23:59 +00:00
print(content_str)
2021-03-21 20:05:06 +00:00
print('')
2022-01-02 12:23:59 +00:00
say_str = 'Confirm delete, yes or no?'
_say_command(say_str, say_str, screenreader,
2021-12-29 21:55:09 +00:00
system_language, espeak)
2021-03-21 20:05:06 +00:00
yesno = input()
if 'y' not in yesno.lower():
2022-01-02 12:23:59 +00:00
say_str = 'Deleting post'
_say_command(say_str, say_str,
2021-12-29 21:55:09 +00:00
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)
2022-01-02 12:23:59 +00:00
refresh_timeline = True
2021-03-21 18:37:06 +00:00
print('')
2021-03-21 13:29:56 +00:00
2022-01-02 12:23:59 +00:00
if refresh_timeline:
if box_json:
_desktop_show_box(indent, follow_requests_json,
your_actor, curr_timeline, box_json,
2021-12-29 21:55:09 +00:00
translate,
screenreader, system_language,
2022-01-02 12:23:59 +00:00
espeak, page_number,
new_replies_exist, new_dms_exist)