mirror of https://gitlab.com/bashrc2/epicyon
				
				
				
			
		
			
				
	
	
		
			2568 lines
		
	
	
		
			114 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			2568 lines
		
	
	
		
			114 KiB
		
	
	
	
		
			Python
		
	
	
__filename__ = "desktop_client.py"
 | 
						|
__author__ = "Bob Mottram"
 | 
						|
__license__ = "AGPL3+"
 | 
						|
__version__ = "1.3.0"
 | 
						|
__maintainer__ = "Bob Mottram"
 | 
						|
__email__ = "bob@libreserver.org"
 | 
						|
__status__ = "Production"
 | 
						|
__module_group__ = "Client"
 | 
						|
 | 
						|
import os
 | 
						|
import html
 | 
						|
import time
 | 
						|
import sys
 | 
						|
import select
 | 
						|
import webbrowser
 | 
						|
import urllib.parse
 | 
						|
from pathlib import Path
 | 
						|
from random import randint
 | 
						|
from utils import get_base_content_from_post
 | 
						|
from utils import has_object_dict
 | 
						|
from utils import get_full_domain
 | 
						|
from utils import is_dm
 | 
						|
from utils import load_translations_from_file
 | 
						|
from utils import remove_html
 | 
						|
from utils import get_nickname_from_actor
 | 
						|
from utils import get_domain_from_actor
 | 
						|
from utils import is_pgp_encrypted
 | 
						|
from utils import local_actor_url
 | 
						|
from session import create_session
 | 
						|
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
 | 
						|
from follow import send_follow_request_via_server
 | 
						|
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:
 | 
						|
    """Shows help
 | 
						|
    """
 | 
						|
    _desktop_clear_screen()
 | 
						|
    indent = '   '
 | 
						|
    print('')
 | 
						|
    print(indent + _highlight_text('Help Commands:'))
 | 
						|
    print('')
 | 
						|
    print(indent + 'quit                                  ' +
 | 
						|
          'Exit from the desktop client')
 | 
						|
    print(indent + 'show dm|sent|inbox|replies|bookmarks  ' +
 | 
						|
          'Show a timeline')
 | 
						|
    print(indent + 'mute                                  ' +
 | 
						|
          'Turn off the screen reader')
 | 
						|
    print(indent + 'speak                                 ' +
 | 
						|
          'Turn on the screen reader')
 | 
						|
    print(indent + 'sounds on                             ' +
 | 
						|
          'Turn on notification sounds')
 | 
						|
    print(indent + 'sounds off                            ' +
 | 
						|
          'Turn off notification sounds')
 | 
						|
    print(indent + 'rp                                    ' +
 | 
						|
          'Repeat the last post')
 | 
						|
    print(indent + 'like                                  ' +
 | 
						|
          'Like the last post')
 | 
						|
    print(indent + 'unlike                                ' +
 | 
						|
          'Unlike the last post')
 | 
						|
    print(indent + 'bookmark                              ' +
 | 
						|
          'Bookmark the last post')
 | 
						|
    print(indent + 'unbookmark                            ' +
 | 
						|
          'Unbookmark the last post')
 | 
						|
    print(indent + 'block [post number|handle]            ' +
 | 
						|
          'Block someone via post number or handle')
 | 
						|
    print(indent + 'unblock [handle]                      ' +
 | 
						|
          'Unblock someone')
 | 
						|
    print(indent + 'mute                                  ' +
 | 
						|
          'Mute the last post')
 | 
						|
    print(indent + 'unmute                                ' +
 | 
						|
          'Unmute the last post')
 | 
						|
    print(indent + 'reply                                 ' +
 | 
						|
          'Reply to the last post')
 | 
						|
    print(indent + 'post                                  ' +
 | 
						|
          'Create a new post')
 | 
						|
    print(indent + 'post to [handle]                      ' +
 | 
						|
          'Create a new direct message')
 | 
						|
    print(indent + 'announce/boost                        ' +
 | 
						|
          'Boost the last post')
 | 
						|
    print(indent + 'follow [handle]                       ' +
 | 
						|
          'Make a follow request')
 | 
						|
    print(indent + 'unfollow [handle]                     ' +
 | 
						|
          'Stop following the give handle')
 | 
						|
    print(indent + 'next                                  ' +
 | 
						|
          'Next page in the timeline')
 | 
						|
    print(indent + 'prev                                  ' +
 | 
						|
          'Previous page in the timeline')
 | 
						|
    print(indent + 'read [post number]                    ' +
 | 
						|
          'Read a post from a timeline')
 | 
						|
    print(indent + 'open [post number]                    ' +
 | 
						|
          'Open web links within a timeline post')
 | 
						|
    print(indent + 'profile [post number or handle]       ' +
 | 
						|
          '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')
 | 
						|
    print(indent + 'pgp                                   ' +
 | 
						|
          'Show your PGP public key')
 | 
						|
    print('')
 | 
						|
 | 
						|
 | 
						|
def _create_desktop_config(actor: str) -> None:
 | 
						|
    """Sets up directories for desktop client configuration
 | 
						|
    """
 | 
						|
    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')
 | 
						|
    nickname = get_nickname_from_actor(actor)
 | 
						|
    domain, port = get_domain_from_actor(actor)
 | 
						|
    handle = nickname + '@' + domain
 | 
						|
    if port not in (443, 80):
 | 
						|
        handle += '_' + str(port)
 | 
						|
    read_posts_dir = home_dir + '/.config/epicyon/' + handle
 | 
						|
    if not os.path.isdir(read_posts_dir):
 | 
						|
        os.mkdir(read_posts_dir)
 | 
						|
 | 
						|
 | 
						|
def _mark_post_as_read(actor: str, post_id: str, post_category: str) -> None:
 | 
						|
    """Marks the given post as read by the given actor
 | 
						|
    """
 | 
						|
    home_dir = str(Path.home())
 | 
						|
    _create_desktop_config(actor)
 | 
						|
    nickname = get_nickname_from_actor(actor)
 | 
						|
    domain, port = get_domain_from_actor(actor)
 | 
						|
    handle = nickname + '@' + domain
 | 
						|
    if port not in (443, 80):
 | 
						|
        handle += '_' + str(port)
 | 
						|
    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
 | 
						|
            post_id += '\n'
 | 
						|
            with open(read_posts_filename, 'r+') as read_file:
 | 
						|
                content = read_file.read()
 | 
						|
                if post_id not in content:
 | 
						|
                    read_file.seek(0, 0)
 | 
						|
                    read_file.write(post_id + content)
 | 
						|
        except Exception as ex:
 | 
						|
            print('EX: Failed to mark post as read' + str(ex))
 | 
						|
    else:
 | 
						|
        with open(read_posts_filename, 'w+') as read_file:
 | 
						|
            read_file.write(post_id + '\n')
 | 
						|
 | 
						|
 | 
						|
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
 | 
						|
    """
 | 
						|
    home_dir = str(Path.home())
 | 
						|
    _create_desktop_config(actor)
 | 
						|
    nickname = get_nickname_from_actor(actor)
 | 
						|
    domain, port = get_domain_from_actor(actor)
 | 
						|
    handle = nickname + '@' + domain
 | 
						|
    if port not in (443, 80):
 | 
						|
        handle += '_' + str(port)
 | 
						|
    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
 | 
						|
 | 
						|
 | 
						|
def _post_is_to_you(actor: str, post_json_object: {}) -> bool:
 | 
						|
    """Returns true if the post is to the actor
 | 
						|
    """
 | 
						|
    to_your_actor = False
 | 
						|
    if post_json_object.get('to'):
 | 
						|
        if actor in post_json_object['to']:
 | 
						|
            to_your_actor = True
 | 
						|
    if not to_your_actor and post_json_object.get('cc'):
 | 
						|
        if actor in post_json_object['cc']:
 | 
						|
            to_your_actor = True
 | 
						|
    if not to_your_actor and has_object_dict(post_json_object):
 | 
						|
        if post_json_object['object'].get('to'):
 | 
						|
            if actor in post_json_object['object']['to']:
 | 
						|
                to_your_actor = True
 | 
						|
        if not to_your_actor and post_json_object['object'].get('cc'):
 | 
						|
            if actor in post_json_object['object']['cc']:
 | 
						|
                to_your_actor = True
 | 
						|
    return to_your_actor
 | 
						|
 | 
						|
 | 
						|
def _new_desktop_notifications(actor: str, inbox_json: {},
 | 
						|
                               notify_json: {}) -> None:
 | 
						|
    """Looks for changes in the inbox and adds notifications
 | 
						|
    """
 | 
						|
    notify_json['dmNotifyChanged'] = False
 | 
						|
    notify_json['repliesNotifyChanged'] = False
 | 
						|
    if not inbox_json:
 | 
						|
        return
 | 
						|
    if not inbox_json.get('orderedItems'):
 | 
						|
        return
 | 
						|
    dm_done = False
 | 
						|
    reply_done = False
 | 
						|
    for post_json_object in inbox_json['orderedItems']:
 | 
						|
        if not post_json_object.get('id'):
 | 
						|
            continue
 | 
						|
        if not post_json_object.get('type'):
 | 
						|
            continue
 | 
						|
        if post_json_object['type'] == 'Announce':
 | 
						|
            continue
 | 
						|
        if not _post_is_to_you(actor, post_json_object):
 | 
						|
            continue
 | 
						|
        if is_dm(post_json_object):
 | 
						|
            if not dm_done:
 | 
						|
                if not _has_read_post(actor, post_json_object['id'], 'dm'):
 | 
						|
                    changed = False
 | 
						|
                    if not notify_json.get('dmPostId'):
 | 
						|
                        changed = True
 | 
						|
                    else:
 | 
						|
                        if notify_json['dmPostId'] != post_json_object['id']:
 | 
						|
                            changed = True
 | 
						|
                    if changed:
 | 
						|
                        notify_json['dmNotify'] = True
 | 
						|
                        notify_json['dmNotifyChanged'] = True
 | 
						|
                        notify_json['dmPostId'] = post_json_object['id']
 | 
						|
                    dm_done = True
 | 
						|
        else:
 | 
						|
            if not reply_done:
 | 
						|
                if not _has_read_post(actor, post_json_object['id'],
 | 
						|
                                      'replies'):
 | 
						|
                    changed = False
 | 
						|
                    if not notify_json.get('repliesPostId'):
 | 
						|
                        changed = True
 | 
						|
                    else:
 | 
						|
                        if notify_json['repliesPostId'] != \
 | 
						|
                           post_json_object['id']:
 | 
						|
                            changed = True
 | 
						|
                    if changed:
 | 
						|
                        notify_json['repliesNotify'] = True
 | 
						|
                        notify_json['repliesNotifyChanged'] = True
 | 
						|
                        notify_json['repliesPostId'] = post_json_object['id']
 | 
						|
                    reply_done = True
 | 
						|
 | 
						|
 | 
						|
def _desktop_clear_screen() -> None:
 | 
						|
    """Clears the screen
 | 
						|
    """
 | 
						|
    os.system('cls' if os.name == 'nt' else 'clear')
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_banner() -> None:
 | 
						|
    """Shows the banner at the top
 | 
						|
    """
 | 
						|
    banner_filename = 'banner.txt'
 | 
						|
    if not os.path.isfile(banner_filename):
 | 
						|
        banner_theme = 'starlight'
 | 
						|
        banner_filename = 'theme/' + banner_theme + '/banner.txt'
 | 
						|
        if not os.path.isfile(banner_filename):
 | 
						|
            return
 | 
						|
    with open(banner_filename, 'r') as banner_file:
 | 
						|
        banner = banner_file.read()
 | 
						|
        if banner:
 | 
						|
            print(banner + '\n')
 | 
						|
 | 
						|
 | 
						|
def _desktop_wait_for_cmd(timeout: int, debug: bool) -> str:
 | 
						|
    """Waits for a command to be entered with a timeout
 | 
						|
    Returns the command, or None on timeout
 | 
						|
    """
 | 
						|
    inp, _, _ = select.select([sys.stdin], [], [], timeout)
 | 
						|
 | 
						|
    if inp:
 | 
						|
        text = sys.stdin.readline().strip()
 | 
						|
        if debug:
 | 
						|
            print("Text entered: " + text)
 | 
						|
        return text
 | 
						|
    if debug:
 | 
						|
        print("Timeout")
 | 
						|
    return None
 | 
						|
 | 
						|
 | 
						|
def _speaker_espeak(espeak, pitch: int, rate: int, srange: int,
 | 
						|
                    say_text: str) -> None:
 | 
						|
    """Speaks the given text with espeak
 | 
						|
    """
 | 
						|
    espeak.set_parameter(espeak.Parameter.Pitch, pitch)
 | 
						|
    espeak.set_parameter(espeak.Parameter.Rate, rate)
 | 
						|
    espeak.set_parameter(espeak.Parameter.Range, srange)
 | 
						|
    espeak.synth(html.unescape(say_text))
 | 
						|
 | 
						|
 | 
						|
def _speaker_picospeaker(pitch: int, rate: int, system_language: str,
 | 
						|
                         say_text: str) -> None:
 | 
						|
    """TTS using picospeaker
 | 
						|
    """
 | 
						|
    speaker_lang = 'en-GB'
 | 
						|
    supported_languages = {
 | 
						|
        "fr": "fr-FR",
 | 
						|
        "es": "es-ES",
 | 
						|
        "de": "de-DE",
 | 
						|
        "it": "it-IT"
 | 
						|
    }
 | 
						|
    for lang, speaker_str in supported_languages.items():
 | 
						|
        if system_language.startswith(lang):
 | 
						|
            speaker_lang = speaker_str
 | 
						|
            break
 | 
						|
    say_text = str(say_text).replace('"', "'")
 | 
						|
    speaker_cmd = 'picospeaker ' + \
 | 
						|
        '-l ' + speaker_lang + \
 | 
						|
        ' -r ' + str(rate) + \
 | 
						|
        ' -p ' + str(pitch) + ' "' + \
 | 
						|
        html.unescape(str(say_text)) + '" 2> /dev/null'
 | 
						|
    os.system(speaker_cmd)
 | 
						|
 | 
						|
 | 
						|
def _play_notification_sound(sound_filename: str,
 | 
						|
                             player: str = 'ffplay') -> None:
 | 
						|
    """Plays a sound
 | 
						|
    """
 | 
						|
    if not os.path.isfile(sound_filename):
 | 
						|
        return
 | 
						|
 | 
						|
    if player == 'ffplay':
 | 
						|
        os.system('ffplay ' + sound_filename +
 | 
						|
                  ' -autoexit -hide_banner -nodisp 2> /dev/null')
 | 
						|
 | 
						|
 | 
						|
def _desktop_notification(notification_type: str,
 | 
						|
                          title: str, message: str) -> None:
 | 
						|
    """Shows a desktop notification
 | 
						|
    """
 | 
						|
    if not notification_type:
 | 
						|
        return
 | 
						|
 | 
						|
    if notification_type == 'notify-send':
 | 
						|
        # Ubuntu
 | 
						|
        os.system('notify-send "' + title + '" "' + message + '"')
 | 
						|
    elif notification_type == 'zenity':
 | 
						|
        # Zenity
 | 
						|
        os.system('zenity --notification --title "' + title +
 | 
						|
                  '" --text="' + message + '"')
 | 
						|
    elif notification_type == 'osascript':
 | 
						|
        # Mac
 | 
						|
        os.system("osascript -e 'display notification \"" +
 | 
						|
                  message + "\" with title \"" + title + "\"'")
 | 
						|
    elif notification_type == 'New-BurntToastNotification':
 | 
						|
        # Windows
 | 
						|
        os.system("New-BurntToastNotification -Text \"" +
 | 
						|
                  title + "\", '" + message + "'")
 | 
						|
 | 
						|
 | 
						|
def _text_to_speech(say_str: str, screenreader: str,
 | 
						|
                    pitch: int, rate: int, srange: int,
 | 
						|
                    system_language: str, espeak=None) -> None:
 | 
						|
    """Say something via TTS
 | 
						|
    """
 | 
						|
    # speak the post content
 | 
						|
    if screenreader == 'espeak':
 | 
						|
        _speaker_espeak(espeak, pitch, rate, srange, say_str)
 | 
						|
    elif screenreader == 'picospeaker':
 | 
						|
        _speaker_picospeaker(pitch, rate, system_language, say_str)
 | 
						|
 | 
						|
 | 
						|
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:
 | 
						|
    """Speaks a command
 | 
						|
    """
 | 
						|
    print(content)
 | 
						|
    if not screenreader:
 | 
						|
        return
 | 
						|
 | 
						|
    pitch = get_speaker_pitch(speaker_name,
 | 
						|
                              screenreader, speaker_gender)
 | 
						|
    rate = get_speaker_rate(speaker_name, screenreader)
 | 
						|
    srange = get_speaker_range(speaker_name)
 | 
						|
 | 
						|
    _text_to_speech(say_str, screenreader,
 | 
						|
                    pitch, rate, srange,
 | 
						|
                    system_language, espeak)
 | 
						|
 | 
						|
 | 
						|
def _desktop_reply_to_post(session, post_id: str,
 | 
						|
                           base_dir: str, nickname: str, password: str,
 | 
						|
                           domain: str, port: int, http_prefix: str,
 | 
						|
                           cached_webfingers: {}, person_cache: {},
 | 
						|
                           debug: bool, subject: str,
 | 
						|
                           screenreader: str, system_language: str,
 | 
						|
                           languages_understood: [],
 | 
						|
                           espeak, conversation_id: str,
 | 
						|
                           low_bandwidth: bool,
 | 
						|
                           content_license_url: str,
 | 
						|
                           signing_priv_key_pem: str) -> None:
 | 
						|
    """Use the desktop client to send a reply to the most recent post
 | 
						|
    """
 | 
						|
    if '://' not in post_id:
 | 
						|
        return
 | 
						|
    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,
 | 
						|
                 screenreader, system_language, espeak)
 | 
						|
    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)
 | 
						|
        return
 | 
						|
    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)
 | 
						|
        return
 | 
						|
    print('')
 | 
						|
    say_str = 'You entered this reply:'
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    _say_command(reply_message, reply_message, screenreader,
 | 
						|
                 system_language, espeak)
 | 
						|
    say_str = 'Send this reply, yes or no?'
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    yesno = input()
 | 
						|
    if 'y' not in yesno.lower():
 | 
						|
        say_str = 'Abandoning reply'
 | 
						|
        _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
        return
 | 
						|
    cc_url = None
 | 
						|
    followers_only = False
 | 
						|
    attach = None
 | 
						|
    media_type = None
 | 
						|
    attached_image_description = None
 | 
						|
    is_article = False
 | 
						|
    subject = None
 | 
						|
    comments_enabled = True
 | 
						|
    city = 'London, England'
 | 
						|
    say_str = 'Sending reply'
 | 
						|
    event_date = None
 | 
						|
    event_time = None
 | 
						|
    location = None
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    if send_post_via_server(signing_priv_key_pem, __version__,
 | 
						|
                            base_dir, session, nickname, password,
 | 
						|
                            domain, port,
 | 
						|
                            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,
 | 
						|
                            debug, post_id, post_id,
 | 
						|
                            conversation_id, subject) == 0:
 | 
						|
        say_str = 'Reply sent'
 | 
						|
    else:
 | 
						|
        say_str = 'Reply failed'
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
 | 
						|
 | 
						|
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: [],
 | 
						|
                      espeak, low_bandwidth: bool,
 | 
						|
                      content_license_url: str,
 | 
						|
                      signing_priv_key_pem: str) -> None:
 | 
						|
    """Use the desktop client to create a new post
 | 
						|
    """
 | 
						|
    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
 | 
						|
    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
 | 
						|
    print('')
 | 
						|
    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():
 | 
						|
        say_str = 'Abandoning new post'
 | 
						|
        _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
        return
 | 
						|
    cc_url = None
 | 
						|
    followers_only = False
 | 
						|
    attach = None
 | 
						|
    media_type = None
 | 
						|
    attached_image_description = None
 | 
						|
    city = 'London, England'
 | 
						|
    is_article = False
 | 
						|
    subject = None
 | 
						|
    comments_enabled = True
 | 
						|
    subject = None
 | 
						|
    say_str = 'Sending'
 | 
						|
    event_date = None
 | 
						|
    event_time = None
 | 
						|
    location = None
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    if send_post_via_server(signing_priv_key_pem, __version__,
 | 
						|
                            base_dir, session, nickname, password,
 | 
						|
                            domain, port,
 | 
						|
                            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,
 | 
						|
                            debug, None, None,
 | 
						|
                            conversation_id, subject) == 0:
 | 
						|
        say_str = 'Post sent'
 | 
						|
    else:
 | 
						|
        say_str = 'Post failed'
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
 | 
						|
 | 
						|
def _safe_message(content: str) -> str:
 | 
						|
    """Removes anything potentially unsafe from a string
 | 
						|
    """
 | 
						|
    return content.replace('`', '').replace('$(', '$ (')
 | 
						|
 | 
						|
 | 
						|
def _timeline_is_empty(box_json: {}) -> bool:
 | 
						|
    """Returns true if the given timeline is empty
 | 
						|
    """
 | 
						|
    empty = False
 | 
						|
    if not box_json:
 | 
						|
        empty = True
 | 
						|
    else:
 | 
						|
        if not isinstance(box_json, dict):
 | 
						|
            empty = True
 | 
						|
        elif not box_json.get('orderedItems'):
 | 
						|
            empty = True
 | 
						|
    return empty
 | 
						|
 | 
						|
 | 
						|
def _get_first_item_id(box_json: {}) -> str:
 | 
						|
    """Returns the id of the first item in the timeline
 | 
						|
    """
 | 
						|
    if _timeline_is_empty(box_json):
 | 
						|
        return
 | 
						|
    if len(box_json['orderedItems']) == 0:
 | 
						|
        return
 | 
						|
    return box_json['orderedItems'][0]['id']
 | 
						|
 | 
						|
 | 
						|
def _text_only_content(content: str) -> str:
 | 
						|
    """Remove formatting from the given string
 | 
						|
    """
 | 
						|
    content = urllib.parse.unquote_plus(content)
 | 
						|
    content = html.unescape(content)
 | 
						|
    return remove_html(content)
 | 
						|
 | 
						|
 | 
						|
def _get_image_description(post_json_object: {}) -> str:
 | 
						|
    """Returns a image description/s on a post
 | 
						|
    """
 | 
						|
    image_description = ''
 | 
						|
    if not post_json_object['object'].get('attachment'):
 | 
						|
        return image_description
 | 
						|
 | 
						|
    attach_list = post_json_object['object']['attachment']
 | 
						|
    if not isinstance(attach_list, list):
 | 
						|
        return image_description
 | 
						|
 | 
						|
    # for each attachment
 | 
						|
    for img in attach_list:
 | 
						|
        if not isinstance(img, dict):
 | 
						|
            continue
 | 
						|
        if not img.get('name'):
 | 
						|
            continue
 | 
						|
        if not isinstance(img['name'], str):
 | 
						|
            continue
 | 
						|
        message_str = img['name']
 | 
						|
        if message_str:
 | 
						|
            message_str = message_str.strip()
 | 
						|
            if not message_str.endswith('.'):
 | 
						|
                image_description += message_str + '. '
 | 
						|
            else:
 | 
						|
                image_description += message_str + ' '
 | 
						|
    return image_description
 | 
						|
 | 
						|
 | 
						|
def _show_likes_on_post(post_json_object: {}, max_likes: int) -> None:
 | 
						|
    """Shows the likes on a post
 | 
						|
    """
 | 
						|
    if not has_object_dict(post_json_object):
 | 
						|
        return
 | 
						|
    if not post_json_object['object'].get('likes'):
 | 
						|
        return
 | 
						|
    object_likes = post_json_object['object']['likes']
 | 
						|
    if not isinstance(object_likes, dict):
 | 
						|
        return
 | 
						|
    if not object_likes.get('items'):
 | 
						|
        return
 | 
						|
    if not isinstance(object_likes['items'], list):
 | 
						|
        return
 | 
						|
    print('')
 | 
						|
    ctr = 0
 | 
						|
    for item in object_likes['items']:
 | 
						|
        print('  ❤ ' + str(item['actor']))
 | 
						|
        ctr += 1
 | 
						|
        if ctr >= max_likes:
 | 
						|
            break
 | 
						|
 | 
						|
 | 
						|
def _show_replies_on_post(post_json_object: {}, max_replies: int) -> None:
 | 
						|
    """Shows the replies on a post
 | 
						|
    """
 | 
						|
    if not has_object_dict(post_json_object):
 | 
						|
        return
 | 
						|
    if not post_json_object['object'].get('replies'):
 | 
						|
        return
 | 
						|
    object_replies = post_json_object['object']['replies']
 | 
						|
    if not isinstance(object_replies, dict):
 | 
						|
        return
 | 
						|
    if not object_replies.get('items'):
 | 
						|
        return
 | 
						|
    if not isinstance(object_replies['items'], list):
 | 
						|
        return
 | 
						|
    print('')
 | 
						|
    ctr = 0
 | 
						|
    for item in object_replies['items']:
 | 
						|
        print('  ↰ ' + str(item['url']))
 | 
						|
        ctr += 1
 | 
						|
        if ctr >= max_replies:
 | 
						|
            break
 | 
						|
 | 
						|
 | 
						|
def _read_local_box_post(session, nickname: str, domain: str,
 | 
						|
                         http_prefix: str, base_dir: str, box_name: str,
 | 
						|
                         page_number: int, index: int, box_json: {},
 | 
						|
                         system_language: str,
 | 
						|
                         screenreader: str, espeak,
 | 
						|
                         translate: {}, your_actor: str,
 | 
						|
                         domain_full: str, person_cache: {},
 | 
						|
                         signing_priv_key_pem: str,
 | 
						|
                         blocked_cache: {}, bold_reading: bool) -> {}:
 | 
						|
    """Reads a post from the given timeline
 | 
						|
    Returns the post json
 | 
						|
    """
 | 
						|
    if _timeline_is_empty(box_json):
 | 
						|
        return {}
 | 
						|
 | 
						|
    post_json_object = _desktop_get_box_post_object(box_json, index)
 | 
						|
    if not post_json_object:
 | 
						|
        return {}
 | 
						|
    gender = 'They/Them'
 | 
						|
 | 
						|
    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)
 | 
						|
    print('')
 | 
						|
 | 
						|
    if post_json_object['type'] == 'Announce':
 | 
						|
        actor = post_json_object['actor']
 | 
						|
        name_str = get_nickname_from_actor(actor)
 | 
						|
        recent_posts_cache = {}
 | 
						|
        allow_local_network_access = False
 | 
						|
        yt_replace_domain = None
 | 
						|
        twitter_replacement_domain = None
 | 
						|
        post_json_object2 = \
 | 
						|
            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,
 | 
						|
                              blocked_cache, bold_reading)
 | 
						|
        if post_json_object2:
 | 
						|
            if has_object_dict(post_json_object2):
 | 
						|
                if post_json_object2['object'].get('attributedTo') and \
 | 
						|
                   post_json_object2['object'].get('content'):
 | 
						|
                    attributed_to = post_json_object2['object']['attributedTo']
 | 
						|
                    content = \
 | 
						|
                        get_base_content_from_post(post_json_object2,
 | 
						|
                                                   system_language)
 | 
						|
                    if isinstance(attributed_to, str) and content:
 | 
						|
                        actor = attributed_to
 | 
						|
                        name_str += ' ' + translate['announces'] + ' ' + \
 | 
						|
                            get_nickname_from_actor(actor)
 | 
						|
                        say_str = name_str
 | 
						|
                        _say_command(say_str, say_str, screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        print('')
 | 
						|
                        if screenreader:
 | 
						|
                            time.sleep(2)
 | 
						|
                        content = \
 | 
						|
                            _text_only_content(content)
 | 
						|
                        content += _get_image_description(post_json_object2)
 | 
						|
                        message_str, _ = \
 | 
						|
                            speakable_text(base_dir, content, translate)
 | 
						|
                        say_str = content
 | 
						|
                        _say_command(say_str, message_str, screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        return post_json_object2
 | 
						|
        return {}
 | 
						|
 | 
						|
    attributed_to = post_json_object['object']['attributedTo']
 | 
						|
    if not attributed_to:
 | 
						|
        return {}
 | 
						|
    content = get_base_content_from_post(post_json_object, system_language)
 | 
						|
    if not isinstance(attributed_to, str) or \
 | 
						|
       not isinstance(content, str):
 | 
						|
        return {}
 | 
						|
    actor = attributed_to
 | 
						|
    name_str = get_nickname_from_actor(actor)
 | 
						|
    content = _text_only_content(content)
 | 
						|
    content += _get_image_description(post_json_object)
 | 
						|
 | 
						|
    if is_pgp_encrypted(content):
 | 
						|
        say_str = 'Encrypted message. Please enter your passphrase.'
 | 
						|
        _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
        content = pgp_decrypt(domain, content, actor, signing_priv_key_pem)
 | 
						|
        if is_pgp_encrypted(content):
 | 
						|
            say_str = 'Message could not be decrypted'
 | 
						|
            _say_command(say_str, say_str,
 | 
						|
                         screenreader, system_language, espeak)
 | 
						|
            return {}
 | 
						|
 | 
						|
    content = _safe_message(content)
 | 
						|
    message_str, _ = speakable_text(base_dir, content, translate)
 | 
						|
 | 
						|
    if screenreader:
 | 
						|
        time.sleep(2)
 | 
						|
 | 
						|
    # say the speaker's name
 | 
						|
    _say_command(name_str, name_str, screenreader,
 | 
						|
                 system_language, espeak, name_str, gender)
 | 
						|
    print('')
 | 
						|
 | 
						|
    if post_json_object['object'].get('inReplyTo'):
 | 
						|
        print('Replying to ' + post_json_object['object']['inReplyTo'] + '\n')
 | 
						|
 | 
						|
    if screenreader:
 | 
						|
        time.sleep(2)
 | 
						|
 | 
						|
    # speak the post content
 | 
						|
    _say_command(content, message_str, screenreader,
 | 
						|
                 system_language, espeak, name_str, gender)
 | 
						|
 | 
						|
    _show_likes_on_post(post_json_object, 10)
 | 
						|
    _show_replies_on_post(post_json_object, 10)
 | 
						|
 | 
						|
    # if the post is addressed to you then mark it as read
 | 
						|
    if _post_is_to_you(your_actor, post_json_object):
 | 
						|
        if is_dm(post_json_object):
 | 
						|
            _mark_post_as_read(your_actor, post_json_object['id'], 'dm')
 | 
						|
        else:
 | 
						|
            _mark_post_as_read(your_actor, post_json_object['id'], 'replies')
 | 
						|
 | 
						|
    return post_json_object
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_actor(base_dir: str, actor_json: {}, translate: {},
 | 
						|
                        system_language: str, screenreader: str,
 | 
						|
                        espeak) -> None:
 | 
						|
    """Shows information for the given actor
 | 
						|
    """
 | 
						|
    actor = actor_json['id']
 | 
						|
    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
 | 
						|
 | 
						|
    say_str = 'Profile for ' + html.unescape(handle)
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    print(actor)
 | 
						|
    if actor_json.get('movedTo'):
 | 
						|
        say_str = 'Moved to ' + html.unescape(actor_json['movedTo'])
 | 
						|
        _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    if actor_json.get('alsoKnownAs'):
 | 
						|
        also_known_as_str = ''
 | 
						|
        ctr = 0
 | 
						|
        for alt_actor in actor_json['alsoKnownAs']:
 | 
						|
            if ctr > 0:
 | 
						|
                also_known_as_str += ', '
 | 
						|
            ctr += 1
 | 
						|
            also_known_as_str += alt_actor
 | 
						|
 | 
						|
        say_str = 'Also known as ' + html.unescape(also_known_as_str)
 | 
						|
        _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    if actor_json.get('summary'):
 | 
						|
        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)
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_profile(session, nickname: str, domain: str,
 | 
						|
                          http_prefix: str, base_dir: str, box_name: str,
 | 
						|
                          page_number: int, index: int, box_json: {},
 | 
						|
                          system_language: str,
 | 
						|
                          screenreader: str, espeak,
 | 
						|
                          translate: {}, your_actor: str,
 | 
						|
                          post_json_object: {},
 | 
						|
                          signing_priv_key_pem: str) -> {}:
 | 
						|
    """Shows the profile of the actor for the given post
 | 
						|
    Returns the actor json
 | 
						|
    """
 | 
						|
    if _timeline_is_empty(box_json):
 | 
						|
        return {}
 | 
						|
 | 
						|
    if not post_json_object:
 | 
						|
        post_json_object = _desktop_get_box_post_object(box_json, index)
 | 
						|
        if not post_json_object:
 | 
						|
            return {}
 | 
						|
 | 
						|
    actor = None
 | 
						|
    if post_json_object['type'] == 'Announce':
 | 
						|
        nickname = get_nickname_from_actor(post_json_object['object'])
 | 
						|
        if nickname:
 | 
						|
            nick_str = '/' + nickname + '/'
 | 
						|
            if nick_str in post_json_object['object']:
 | 
						|
                actor = \
 | 
						|
                    post_json_object['object'].split(nick_str)[0] + \
 | 
						|
                    '/' + nickname
 | 
						|
    else:
 | 
						|
        actor = post_json_object['object']['attributedTo']
 | 
						|
 | 
						|
    if not actor:
 | 
						|
        return {}
 | 
						|
 | 
						|
    is_http = False
 | 
						|
    if 'http://' in actor:
 | 
						|
        is_http = True
 | 
						|
    actor_json, _ = \
 | 
						|
        get_actor_json(domain, actor, is_http, False, False, True,
 | 
						|
                       signing_priv_key_pem, session)
 | 
						|
 | 
						|
    _desktop_show_actor(base_dir, actor_json, translate,
 | 
						|
                        system_language, screenreader, espeak)
 | 
						|
 | 
						|
    return actor_json
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_profile_from_handle(session, nickname: str, domain: str,
 | 
						|
                                      http_prefix: str, base_dir: str,
 | 
						|
                                      box_name: str, handle: str,
 | 
						|
                                      system_language: str,
 | 
						|
                                      screenreader: str, espeak,
 | 
						|
                                      translate: {}, your_actor: str,
 | 
						|
                                      post_json_object: {},
 | 
						|
                                      signing_priv_key_pem: str) -> {}:
 | 
						|
    """Shows the profile for a handle
 | 
						|
    Returns the actor json
 | 
						|
    """
 | 
						|
    actor_json, _ = \
 | 
						|
        get_actor_json(domain, handle, False, False, False, True,
 | 
						|
                       signing_priv_key_pem, session)
 | 
						|
 | 
						|
    _desktop_show_actor(base_dir, actor_json, translate,
 | 
						|
                        system_language, screenreader, espeak)
 | 
						|
 | 
						|
    return actor_json
 | 
						|
 | 
						|
 | 
						|
def _desktop_get_box_post_object(box_json: {}, index: int) -> {}:
 | 
						|
    """Gets the post with the given index from the timeline
 | 
						|
    """
 | 
						|
    ctr = 0
 | 
						|
    for post_json_object in box_json['orderedItems']:
 | 
						|
        if not post_json_object.get('type'):
 | 
						|
            continue
 | 
						|
        if not post_json_object.get('object'):
 | 
						|
            continue
 | 
						|
        if post_json_object['type'] == 'Announce':
 | 
						|
            if not isinstance(post_json_object['object'], str):
 | 
						|
                continue
 | 
						|
            ctr += 1
 | 
						|
            if ctr == index:
 | 
						|
                return post_json_object
 | 
						|
            continue
 | 
						|
        if not has_object_dict(post_json_object):
 | 
						|
            continue
 | 
						|
        if not post_json_object['object'].get('published'):
 | 
						|
            continue
 | 
						|
        if not post_json_object['object'].get('content'):
 | 
						|
            continue
 | 
						|
        ctr += 1
 | 
						|
        if ctr == index:
 | 
						|
            return post_json_object
 | 
						|
    return None
 | 
						|
 | 
						|
 | 
						|
def _format_published(published: str) -> str:
 | 
						|
    """Formats the published time for display on timeline
 | 
						|
    """
 | 
						|
    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'
 | 
						|
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
 | 
						|
def _highlight_text(text: str) -> str:
 | 
						|
    """Returns a highlighted version of the given text
 | 
						|
    """
 | 
						|
    return '\33[7m' + text + '\33[0m'
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_box(indent: str,
 | 
						|
                      follow_requests_json: {},
 | 
						|
                      your_actor: str, box_name: str, box_json: {},
 | 
						|
                      translate: {},
 | 
						|
                      screenreader: str, system_language: str, espeak,
 | 
						|
                      page_number: int,
 | 
						|
                      newReplies: bool,
 | 
						|
                      newDMs: bool) -> bool:
 | 
						|
    """Shows online timeline
 | 
						|
    """
 | 
						|
    number_width = 2
 | 
						|
    name_width = 16
 | 
						|
    content_width = 50
 | 
						|
 | 
						|
    # title
 | 
						|
    _desktop_clear_screen()
 | 
						|
    _desktop_show_banner()
 | 
						|
 | 
						|
    notification_icons = ''
 | 
						|
    if box_name.startswith('tl'):
 | 
						|
        box_name_str = box_name[2:]
 | 
						|
    else:
 | 
						|
        box_name_str = box_name
 | 
						|
    title_str = _highlight_text(box_name_str.upper())
 | 
						|
    # if newDMs:
 | 
						|
    #     notification_icons += ' 📩'
 | 
						|
    # if newReplies:
 | 
						|
    #     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
 | 
						|
    for post_json_object in box_json['orderedItems']:
 | 
						|
        if not post_json_object.get('type'):
 | 
						|
            continue
 | 
						|
        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):
 | 
						|
                    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)
 | 
						|
                    published = \
 | 
						|
                        _format_published(post_json_object['published'])
 | 
						|
                    announced_nickname = \
 | 
						|
                        get_nickname_from_actor(post_json_object['object'])
 | 
						|
                    announced_domain, _ = \
 | 
						|
                        get_domain_from_actor(post_json_object['object'])
 | 
						|
                    announced_handle = \
 | 
						|
                        announced_nickname + '@' + announced_domain
 | 
						|
                    line_str = \
 | 
						|
                        indent + str(pos_str) + ' | ' + name + ' | ' + \
 | 
						|
                        published + ' | ' + \
 | 
						|
                        _pad_to_width(announced_handle, content_width)
 | 
						|
                    print(line_str)
 | 
						|
                    ctr += 1
 | 
						|
                    continue
 | 
						|
 | 
						|
        if not has_object_dict(post_json_object):
 | 
						|
            continue
 | 
						|
        if not post_json_object['object'].get('published'):
 | 
						|
            continue
 | 
						|
        if not post_json_object['object'].get('content'):
 | 
						|
            continue
 | 
						|
        ctr_str = str(ctr)
 | 
						|
        pos_str = _pad_to_width(ctr_str, number_width)
 | 
						|
 | 
						|
        author_actor = post_json_object['object']['attributedTo']
 | 
						|
        content_warning = None
 | 
						|
        if post_json_object['object'].get('summary'):
 | 
						|
            content_warning = '⚡' + \
 | 
						|
                _pad_to_width(post_json_object['object']['summary'],
 | 
						|
                              content_width)
 | 
						|
        name = get_nickname_from_actor(author_actor)
 | 
						|
 | 
						|
        # append icons to the end of the name
 | 
						|
        space_added = False
 | 
						|
        if post_json_object['object'].get('inReplyTo'):
 | 
						|
            if not space_added:
 | 
						|
                space_added = True
 | 
						|
                name += ' '
 | 
						|
            name += '↲'
 | 
						|
            if post_json_object['object'].get('replies'):
 | 
						|
                replies_list = post_json_object['object']['replies']
 | 
						|
                if replies_list.get('items'):
 | 
						|
                    items = replies_list['items']
 | 
						|
                    for i in range(int(items)):
 | 
						|
                        name += '↰'
 | 
						|
                        if i > 10:
 | 
						|
                            break
 | 
						|
        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
 | 
						|
                name += ' '
 | 
						|
            name += '❤'
 | 
						|
        name = _pad_to_width(name, name_width)
 | 
						|
 | 
						|
        published = _format_published(post_json_object['published'])
 | 
						|
 | 
						|
        content_str = get_base_content_from_post(post_json_object,
 | 
						|
                                                 system_language)
 | 
						|
        content = _text_only_content(content_str)
 | 
						|
        if box_name != 'dm':
 | 
						|
            if is_dm(post_json_object):
 | 
						|
                content = '📧' + content
 | 
						|
        if not content_warning:
 | 
						|
            if is_pgp_encrypted(content):
 | 
						|
                content = '🔒' + content
 | 
						|
            elif '://' in content:
 | 
						|
                content = '🔗' + content
 | 
						|
            content = _pad_to_width(content, content_width)
 | 
						|
        else:
 | 
						|
            # display content warning
 | 
						|
            if is_pgp_encrypted(content):
 | 
						|
                content = '🔒' + content_warning
 | 
						|
            else:
 | 
						|
                if '://' in content:
 | 
						|
                    content = '🔗' + content_warning
 | 
						|
                else:
 | 
						|
                    content = content_warning
 | 
						|
        if post_json_object['object'].get('ignores'):
 | 
						|
            content = '🔇'
 | 
						|
        if post_json_object['object'].get('bookmarks'):
 | 
						|
            content = '🔖' + content
 | 
						|
        if '\n' in content:
 | 
						|
            content = content.replace('\n', ' ')
 | 
						|
        line_str = indent + str(pos_str) + ' | ' + name + ' | ' + \
 | 
						|
            published + ' | ' + content
 | 
						|
        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'],
 | 
						|
                                      'replies'):
 | 
						|
                    line_str = _highlight_text(line_str)
 | 
						|
        print(line_str)
 | 
						|
        ctr += 1
 | 
						|
 | 
						|
    if follow_requests_json:
 | 
						|
        _desktop_show_follow_requests(follow_requests_json, translate)
 | 
						|
 | 
						|
    print('')
 | 
						|
 | 
						|
    # say the post number range
 | 
						|
    say_str = indent + box_name_str + ' page ' + str(page_number) + \
 | 
						|
        ' containing ' + str(ctr - 1) + ' posts. '
 | 
						|
    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
 | 
						|
 | 
						|
 | 
						|
def _desktop_new_dm(session, to_handle: str,
 | 
						|
                    base_dir: str, nickname: str, password: str,
 | 
						|
                    domain: str, port: int, http_prefix: str,
 | 
						|
                    cached_webfingers: {}, person_cache: {},
 | 
						|
                    debug: bool,
 | 
						|
                    screenreader: str, system_language: str,
 | 
						|
                    languages_understood: [],
 | 
						|
                    espeak, low_bandwidth: bool,
 | 
						|
                    content_license_url: str,
 | 
						|
                    signing_priv_key_pem: str) -> None:
 | 
						|
    """Use the desktop client to create a new direct message
 | 
						|
    which can include multiple destination handles
 | 
						|
    """
 | 
						|
    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(';')
 | 
						|
    else:
 | 
						|
        handles_list = [to_handle]
 | 
						|
 | 
						|
    for handle in handles_list:
 | 
						|
        handle = handle.strip()
 | 
						|
        _desktop_new_dm_base(session, handle,
 | 
						|
                             base_dir, nickname, password,
 | 
						|
                             domain, port, http_prefix,
 | 
						|
                             cached_webfingers, person_cache,
 | 
						|
                             debug,
 | 
						|
                             screenreader, system_language,
 | 
						|
                             languages_understood,
 | 
						|
                             espeak, low_bandwidth,
 | 
						|
                             content_license_url,
 | 
						|
                             signing_priv_key_pem)
 | 
						|
 | 
						|
 | 
						|
def _desktop_new_dm_base(session, to_handle: str,
 | 
						|
                         base_dir: str, nickname: str, password: str,
 | 
						|
                         domain: str, port: int, http_prefix: str,
 | 
						|
                         cached_webfingers: {}, person_cache: {},
 | 
						|
                         debug: bool,
 | 
						|
                         screenreader: str, system_language: str,
 | 
						|
                         languages_understood: [],
 | 
						|
                         espeak, low_bandwidth: bool,
 | 
						|
                         content_license_url: str,
 | 
						|
                         signing_priv_key_pem: str) -> None:
 | 
						|
    """Use the desktop client to create a new direct message
 | 
						|
    """
 | 
						|
    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
 | 
						|
    else:
 | 
						|
        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)
 | 
						|
        return
 | 
						|
    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)
 | 
						|
        return
 | 
						|
    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
 | 
						|
    attach = None
 | 
						|
    media_type = None
 | 
						|
    attached_image_description = None
 | 
						|
    city = 'London, England'
 | 
						|
    is_article = False
 | 
						|
    subject = None
 | 
						|
    comments_enabled = True
 | 
						|
    subject = None
 | 
						|
 | 
						|
    # if there is a local PGP key then attempt to encrypt the DM
 | 
						|
    # using the PGP public key of the recipient
 | 
						|
    if has_local_pg_pkey():
 | 
						|
        say_str = \
 | 
						|
            'Local PGP key detected...' + \
 | 
						|
            '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"
 | 
						|
            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,
 | 
						|
                                 signing_priv_key_pem)
 | 
						|
        if not cipher_text:
 | 
						|
            say_str = \
 | 
						|
                to_handle + ' has no PGP public key. ' + \
 | 
						|
                'Your message will be sent in clear text'
 | 
						|
            _say_command(say_str, say_str,
 | 
						|
                         screenreader, system_language, espeak)
 | 
						|
        else:
 | 
						|
            new_message = cipher_text
 | 
						|
            say_str = 'Message encrypted'
 | 
						|
            _say_command(say_str, say_str,
 | 
						|
                         screenreader, system_language, espeak)
 | 
						|
 | 
						|
    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():
 | 
						|
        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
 | 
						|
 | 
						|
    say_str = 'Sending'
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
    if send_post_via_server(signing_priv_key_pem, __version__,
 | 
						|
                            base_dir, session, nickname, password,
 | 
						|
                            domain, port,
 | 
						|
                            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,
 | 
						|
                            debug, None, None,
 | 
						|
                            conversation_id, subject) == 0:
 | 
						|
        say_str = 'Direct message sent'
 | 
						|
    else:
 | 
						|
        say_str = 'Direct message failed'
 | 
						|
    _say_command(say_str, say_str, screenreader, system_language, espeak)
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_follow_requests(follow_requests_json: {},
 | 
						|
                                  translate: {}) -> None:
 | 
						|
    """Shows any follow requests
 | 
						|
    """
 | 
						|
    if not isinstance(follow_requests_json, dict):
 | 
						|
        return
 | 
						|
    if not follow_requests_json.get('orderedItems'):
 | 
						|
        return
 | 
						|
    if not follow_requests_json['orderedItems']:
 | 
						|
        return
 | 
						|
    indent = '   '
 | 
						|
    print('')
 | 
						|
    print(indent + 'Follow requests:')
 | 
						|
    print('')
 | 
						|
    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 + '  👤 ' +
 | 
						|
              handle_nickname + '@' + handle_domain_full)
 | 
						|
 | 
						|
 | 
						|
def _desktop_show_following(following_json: {}, translate: {},
 | 
						|
                            page_number: int, indent: str,
 | 
						|
                            followType='following') -> None:
 | 
						|
    """Shows a page of accounts followed
 | 
						|
    """
 | 
						|
    if not isinstance(following_json, dict):
 | 
						|
        return
 | 
						|
    if not following_json.get('orderedItems'):
 | 
						|
        return
 | 
						|
    if not following_json['orderedItems']:
 | 
						|
        return
 | 
						|
    print('')
 | 
						|
    if followType == 'following':
 | 
						|
        print(indent + 'Following page ' + str(page_number))
 | 
						|
    elif followType == 'followers':
 | 
						|
        print(indent + 'Followers page ' + str(page_number))
 | 
						|
    print('')
 | 
						|
    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 + '  👤 ' +
 | 
						|
              handle_nickname + '@' + handle_domain_full)
 | 
						|
 | 
						|
 | 
						|
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,
 | 
						|
                       notification_sounds: bool,
 | 
						|
                       notification_type: str,
 | 
						|
                       no_key_press: bool,
 | 
						|
                       store_inbox_posts: bool,
 | 
						|
                       show_new_posts: bool,
 | 
						|
                       language: str,
 | 
						|
                       debug: bool, low_bandwidth: bool) -> None:
 | 
						|
    """Runs the desktop and screen reader client,
 | 
						|
    which announces new inbox items
 | 
						|
    """
 | 
						|
    bold_reading = False
 | 
						|
 | 
						|
    # TODO: this should probably be retrieved somehow from the server
 | 
						|
    signing_priv_key_pem = None
 | 
						|
 | 
						|
    content_license_url = 'https://creativecommons.org/licenses/by/4.0'
 | 
						|
 | 
						|
    blocked_cache = {}
 | 
						|
    languages_understood = []
 | 
						|
 | 
						|
    indent = '   '
 | 
						|
    if show_new_posts:
 | 
						|
        indent = ''
 | 
						|
 | 
						|
    _desktop_clear_screen()
 | 
						|
    _desktop_show_banner()
 | 
						|
 | 
						|
    espeak = None
 | 
						|
    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
 | 
						|
 | 
						|
        say_str = indent + 'Running ' + screenreader + ' for ' + \
 | 
						|
            nickname + '@' + domain
 | 
						|
        _say_command(say_str, say_str, screenreader,
 | 
						|
                     system_language, espeak)
 | 
						|
    else:
 | 
						|
        print(indent + 'Running desktop notifications for ' +
 | 
						|
              nickname + '@' + domain)
 | 
						|
    if notification_sounds:
 | 
						|
        say_str = indent + 'Notification sounds on'
 | 
						|
    else:
 | 
						|
        say_str = indent + 'Notification sounds off'
 | 
						|
    _say_command(say_str, say_str, screenreader,
 | 
						|
                 system_language, espeak)
 | 
						|
 | 
						|
    curr_timeline = 'inbox'
 | 
						|
    page_number = 1
 | 
						|
 | 
						|
    post_json_object = {}
 | 
						|
    original_screen_reader = screenreader
 | 
						|
    sounds_dir = 'theme/default/sounds/'
 | 
						|
    # prev_say = ''
 | 
						|
    # prev_calendar = False
 | 
						|
    # prev_follow = False
 | 
						|
    # prev_like = ''
 | 
						|
    # prev_share = False
 | 
						|
    dm_sound_filename = sounds_dir + 'dm.ogg'
 | 
						|
    reply_sound_filename = sounds_dir + 'reply.ogg'
 | 
						|
    # 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'
 | 
						|
    player = 'ffplay'
 | 
						|
    name_str = None
 | 
						|
    gender = None
 | 
						|
    message_str = None
 | 
						|
    content = None
 | 
						|
    cached_webfingers = {}
 | 
						|
    person_cache = {}
 | 
						|
    new_replies_exist = False
 | 
						|
    new_dms_exist = False
 | 
						|
    pgp_key_upload = False
 | 
						|
 | 
						|
    say_str = indent + 'Loading translations file'
 | 
						|
    _say_command(say_str, say_str, screenreader,
 | 
						|
                 system_language, espeak)
 | 
						|
    translate, system_language = \
 | 
						|
        load_translations_from_file(base_dir, language)
 | 
						|
 | 
						|
    say_str = indent + 'Connecting...'
 | 
						|
    _say_command(say_str, say_str, screenreader,
 | 
						|
                 system_language, espeak)
 | 
						|
    session = create_session(proxy_type)
 | 
						|
 | 
						|
    say_str = indent + '/q or /quit to exit'
 | 
						|
    _say_command(say_str, say_str, screenreader,
 | 
						|
                 system_language, espeak)
 | 
						|
 | 
						|
    domain_full = get_full_domain(domain, port)
 | 
						|
    your_actor = local_actor_url(http_prefix, nickname, domain_full)
 | 
						|
    actor_json = None
 | 
						|
 | 
						|
    notify_json = {
 | 
						|
        "dmPostId": "Initial",
 | 
						|
        "dmNotify": False,
 | 
						|
        "dmNotifyChanged": False,
 | 
						|
        "repliesPostId": "Initial",
 | 
						|
        "repliesNotify": False,
 | 
						|
        "repliesNotifyChanged": False
 | 
						|
    }
 | 
						|
    prev_timeline_first_id = ''
 | 
						|
    desktop_shown = False
 | 
						|
    while (1):
 | 
						|
        if not pgp_key_upload:
 | 
						|
            if not has_local_pg_pkey():
 | 
						|
                print('No PGP public key was found')
 | 
						|
            else:
 | 
						|
                say_str = indent + 'Uploading PGP public key'
 | 
						|
                _say_command(say_str, say_str, screenreader,
 | 
						|
                             system_language, espeak)
 | 
						|
                pgp_public_key_upload(base_dir, session,
 | 
						|
                                      nickname, password,
 | 
						|
                                      domain, port, http_prefix,
 | 
						|
                                      cached_webfingers, person_cache,
 | 
						|
                                      debug, False,
 | 
						|
                                      signing_priv_key_pem)
 | 
						|
                say_str = indent + 'PGP public key uploaded'
 | 
						|
                _say_command(say_str, say_str, screenreader,
 | 
						|
                             system_language, espeak)
 | 
						|
            pgp_key_upload = True
 | 
						|
 | 
						|
        box_json = c2s_box_json(base_dir, session,
 | 
						|
                                nickname, password,
 | 
						|
                                domain, port, http_prefix,
 | 
						|
                                curr_timeline, page_number,
 | 
						|
                                debug, signing_priv_key_pem)
 | 
						|
 | 
						|
        follow_requests_json = \
 | 
						|
            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)
 | 
						|
 | 
						|
        if not (curr_timeline == 'inbox' and page_number == 1):
 | 
						|
            # monitor the inbox to generate notifications
 | 
						|
            inbox_json = c2s_box_json(base_dir, session,
 | 
						|
                                      nickname, password,
 | 
						|
                                      domain, port, http_prefix,
 | 
						|
                                      'inbox', 1, debug,
 | 
						|
                                      signing_priv_key_pem)
 | 
						|
        else:
 | 
						|
            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,
 | 
						|
                                          "Epicyon",
 | 
						|
                                          "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,
 | 
						|
                                          "Epicyon",
 | 
						|
                                          "New reply " +
 | 
						|
                                          your_actor + '/replies')
 | 
						|
                    if notification_sounds:
 | 
						|
                        _play_notification_sound(reply_sound_filename, player)
 | 
						|
 | 
						|
        if box_json:
 | 
						|
            timeline_first_id = _get_first_item_id(box_json)
 | 
						|
            if timeline_first_id != prev_timeline_first_id:
 | 
						|
                _desktop_clear_screen()
 | 
						|
                _desktop_show_box(indent, follow_requests_json,
 | 
						|
                                  your_actor, curr_timeline, box_json,
 | 
						|
                                  translate,
 | 
						|
                                  None, system_language, espeak,
 | 
						|
                                  page_number,
 | 
						|
                                  new_replies_exist,
 | 
						|
                                  new_dms_exist)
 | 
						|
                desktop_shown = True
 | 
						|
            prev_timeline_first_id = timeline_first_id
 | 
						|
        else:
 | 
						|
            session = create_session(proxy_type)
 | 
						|
            if not desktop_shown:
 | 
						|
                if not session:
 | 
						|
                    print('No session\n')
 | 
						|
 | 
						|
                _desktop_clear_screen()
 | 
						|
                _desktop_show_banner()
 | 
						|
                print('No posts\n')
 | 
						|
                if proxy_type == 'tor':
 | 
						|
                    print('You may need to run the desktop client ' +
 | 
						|
                          'with the --http option')
 | 
						|
 | 
						|
        # wait for a while, or until a key is pressed
 | 
						|
        if no_key_press:
 | 
						|
            time.sleep(10)
 | 
						|
        else:
 | 
						|
            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,
 | 
						|
                             system_language, espeak)
 | 
						|
                if screenreader:
 | 
						|
                    command_str = _desktop_wait_for_cmd(2, debug)
 | 
						|
                break
 | 
						|
            if command_str.startswith('show dm'):
 | 
						|
                page_number = 1
 | 
						|
                prev_timeline_first_id = ''
 | 
						|
                curr_timeline = 'dm'
 | 
						|
                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,
 | 
						|
                                      translate,
 | 
						|
                                      screenreader, system_language, espeak,
 | 
						|
                                      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 = ''
 | 
						|
                curr_timeline = 'tlreplies'
 | 
						|
                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,
 | 
						|
                                      translate,
 | 
						|
                                      screenreader, system_language, espeak,
 | 
						|
                                      page_number,
 | 
						|
                                      new_replies_exist, new_dms_exist)
 | 
						|
                # Turn off the replies indicator
 | 
						|
                new_replies_exist = False
 | 
						|
            elif command_str.startswith('show b'):
 | 
						|
                page_number = 1
 | 
						|
                prev_timeline_first_id = ''
 | 
						|
                curr_timeline = 'tlbookmarks'
 | 
						|
                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,
 | 
						|
                                      translate,
 | 
						|
                                      screenreader, system_language, espeak,
 | 
						|
                                      page_number,
 | 
						|
                                      new_replies_exist, new_dms_exist)
 | 
						|
                # Turn off the replies indicator
 | 
						|
                new_replies_exist = False
 | 
						|
            elif (command_str.startswith('show sen') or
 | 
						|
                  command_str.startswith('show out')):
 | 
						|
                page_number = 1
 | 
						|
                prev_timeline_first_id = ''
 | 
						|
                curr_timeline = 'outbox'
 | 
						|
                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,
 | 
						|
                                      translate,
 | 
						|
                                      screenreader, system_language, espeak,
 | 
						|
                                      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 = ''
 | 
						|
                curr_timeline = 'inbox'
 | 
						|
                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,
 | 
						|
                                      translate,
 | 
						|
                                      screenreader, system_language, espeak,
 | 
						|
                                      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'
 | 
						|
                else:
 | 
						|
                    post_index_str = command_str.split('read ')[1]
 | 
						|
                if box_json and post_index_str.isdigit():
 | 
						|
                    _desktop_clear_screen()
 | 
						|
                    _desktop_show_banner()
 | 
						|
                    post_index = int(post_index_str)
 | 
						|
                    post_json_object = \
 | 
						|
                        _read_local_box_post(session, nickname, domain,
 | 
						|
                                             http_prefix, base_dir,
 | 
						|
                                             curr_timeline,
 | 
						|
                                             page_number, post_index, box_json,
 | 
						|
                                             system_language, screenreader,
 | 
						|
                                             espeak, translate, your_actor,
 | 
						|
                                             domain_full, person_cache,
 | 
						|
                                             signing_priv_key_pem,
 | 
						|
                                             blocked_cache, bold_reading)
 | 
						|
                    print('')
 | 
						|
                    say_str = 'Press Enter to continue...'
 | 
						|
                    say_str2 = _highlight_text(say_str)
 | 
						|
                    _say_command(say_str2, say_str,
 | 
						|
                                 screenreader, system_language, espeak)
 | 
						|
                    input()
 | 
						|
                    prev_timeline_first_id = ''
 | 
						|
                    refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            elif (command_str.startswith('profile ') or
 | 
						|
                  command_str == 'profile'):
 | 
						|
                actor_json = None
 | 
						|
                if command_str == 'profile':
 | 
						|
                    if post_json_object:
 | 
						|
                        actor_json = \
 | 
						|
                            _desktop_show_profile(session, nickname, domain,
 | 
						|
                                                  http_prefix, base_dir,
 | 
						|
                                                  curr_timeline,
 | 
						|
                                                  page_number, post_index,
 | 
						|
                                                  box_json,
 | 
						|
                                                  system_language,
 | 
						|
                                                  screenreader,
 | 
						|
                                                  espeak, translate,
 | 
						|
                                                  your_actor,
 | 
						|
                                                  post_json_object,
 | 
						|
                                                  signing_priv_key_pem)
 | 
						|
                    else:
 | 
						|
                        post_index_str = '1'
 | 
						|
                else:
 | 
						|
                    post_index_str = command_str.split('profile ')[1]
 | 
						|
 | 
						|
                if not post_index_str.isdigit():
 | 
						|
                    profile_handle = post_index_str
 | 
						|
                    _desktop_clear_screen()
 | 
						|
                    _desktop_show_banner()
 | 
						|
                    _desktop_show_profile_from_handle(session,
 | 
						|
                                                      nickname, domain,
 | 
						|
                                                      http_prefix, base_dir,
 | 
						|
                                                      curr_timeline,
 | 
						|
                                                      profile_handle,
 | 
						|
                                                      system_language,
 | 
						|
                                                      screenreader,
 | 
						|
                                                      espeak, translate,
 | 
						|
                                                      your_actor,
 | 
						|
                                                      None,
 | 
						|
                                                      signing_priv_key_pem)
 | 
						|
                    say_str = 'Press Enter to continue...'
 | 
						|
                    say_str2 = _highlight_text(say_str)
 | 
						|
                    _say_command(say_str2, say_str,
 | 
						|
                                 screenreader, system_language, espeak)
 | 
						|
                    input()
 | 
						|
                    prev_timeline_first_id = ''
 | 
						|
                    refresh_timeline = True
 | 
						|
                elif not actor_json and box_json:
 | 
						|
                    _desktop_clear_screen()
 | 
						|
                    _desktop_show_banner()
 | 
						|
                    post_index = int(post_index_str)
 | 
						|
                    actor_json = \
 | 
						|
                        _desktop_show_profile(session, nickname, domain,
 | 
						|
                                              http_prefix, base_dir,
 | 
						|
                                              curr_timeline,
 | 
						|
                                              page_number, post_index,
 | 
						|
                                              box_json,
 | 
						|
                                              system_language, screenreader,
 | 
						|
                                              espeak, translate, your_actor,
 | 
						|
                                              None, signing_priv_key_pem)
 | 
						|
                    say_str = 'Press Enter to continue...'
 | 
						|
                    say_str2 = _highlight_text(say_str)
 | 
						|
                    _say_command(say_str2, say_str,
 | 
						|
                                 screenreader, system_language, espeak)
 | 
						|
                    input()
 | 
						|
                    prev_timeline_first_id = ''
 | 
						|
                    refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            elif command_str in ('reply', 'r'):
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        post_id = post_json_object['id']
 | 
						|
                        subject = None
 | 
						|
                        if post_json_object['object'].get('summary'):
 | 
						|
                            subject = post_json_object['object']['summary']
 | 
						|
                        conversation_id = None
 | 
						|
                        if post_json_object['object'].get('conversation'):
 | 
						|
                            conversation_id = \
 | 
						|
                                post_json_object['object']['conversation']
 | 
						|
                        session_reply = create_session(proxy_type)
 | 
						|
                        _desktop_reply_to_post(session_reply, post_id,
 | 
						|
                                               base_dir, nickname, password,
 | 
						|
                                               domain, port, http_prefix,
 | 
						|
                                               cached_webfingers, person_cache,
 | 
						|
                                               debug, subject,
 | 
						|
                                               screenreader, system_language,
 | 
						|
                                               languages_understood,
 | 
						|
                                               espeak, conversation_id,
 | 
						|
                                               low_bandwidth,
 | 
						|
                                               content_license_url,
 | 
						|
                                               signing_priv_key_pem)
 | 
						|
                refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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 ', ' ')
 | 
						|
                    # direct message
 | 
						|
                    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,
 | 
						|
                                        base_dir, nickname, password,
 | 
						|
                                        domain, port, http_prefix,
 | 
						|
                                        cached_webfingers, person_cache,
 | 
						|
                                        debug,
 | 
						|
                                        screenreader, system_language,
 | 
						|
                                        languages_understood,
 | 
						|
                                        espeak, low_bandwidth,
 | 
						|
                                        content_license_url,
 | 
						|
                                        signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                else:
 | 
						|
                    # public post
 | 
						|
                    _desktop_new_post(session_post,
 | 
						|
                                      base_dir, nickname, password,
 | 
						|
                                      domain, port, http_prefix,
 | 
						|
                                      cached_webfingers, person_cache,
 | 
						|
                                      debug,
 | 
						|
                                      screenreader, system_language,
 | 
						|
                                      languages_understood,
 | 
						|
                                      espeak, low_bandwidth,
 | 
						|
                                      content_license_url,
 | 
						|
                                      signing_priv_key_pem)
 | 
						|
                    refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        like_actor = post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Liking post by ' + \
 | 
						|
                            get_nickname_from_actor(like_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        session_like = create_session(proxy_type)
 | 
						|
                        send_like_via_server(base_dir, session_like,
 | 
						|
                                             nickname, password,
 | 
						|
                                             domain, port, http_prefix,
 | 
						|
                                             post_json_object['id'],
 | 
						|
                                             cached_webfingers, person_cache,
 | 
						|
                                             False, __version__,
 | 
						|
                                             signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        mute_actor = post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Unmuting post by ' + \
 | 
						|
                            get_nickname_from_actor(mute_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        session_mute = create_session(proxy_type)
 | 
						|
                        send_undo_mute_via_server(base_dir, session_mute,
 | 
						|
                                                  nickname, password,
 | 
						|
                                                  domain, port,
 | 
						|
                                                  http_prefix,
 | 
						|
                                                  post_json_object['id'],
 | 
						|
                                                  cached_webfingers,
 | 
						|
                                                  person_cache,
 | 
						|
                                                  False, __version__,
 | 
						|
                                                  signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        mute_actor = post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Muting post by ' + \
 | 
						|
                            get_nickname_from_actor(mute_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        session_mute = create_session(proxy_type)
 | 
						|
                        send_mute_via_server(base_dir, session_mute,
 | 
						|
                                             nickname, password,
 | 
						|
                                             domain, port,
 | 
						|
                                             http_prefix,
 | 
						|
                                             post_json_object['id'],
 | 
						|
                                             cached_webfingers, person_cache,
 | 
						|
                                             False, __version__,
 | 
						|
                                             signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        bm_actor = post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Unbookmarking post by ' + \
 | 
						|
                            get_nickname_from_actor(bm_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        sessionbm = create_session(proxy_type)
 | 
						|
                        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)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        bm_actor = post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Bookmarking post by ' + \
 | 
						|
                            get_nickname_from_actor(bm_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        sessionbm = create_session(proxy_type)
 | 
						|
                        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)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id') and \
 | 
						|
                       post_json_object.get('object'):
 | 
						|
                        if has_object_dict(post_json_object):
 | 
						|
                            if post_json_object['object'].get('attributedTo'):
 | 
						|
                                block_actor = \
 | 
						|
                                    post_json_object['object']['attributedTo']
 | 
						|
                                say_str = 'Unblocking ' + \
 | 
						|
                                    get_nickname_from_actor(block_actor)
 | 
						|
                                _say_command(say_str, say_str,
 | 
						|
                                             screenreader,
 | 
						|
                                             system_language, espeak)
 | 
						|
                                session_block = create_session(proxy_type)
 | 
						|
                                sign_priv_key_pem = signing_priv_key_pem
 | 
						|
                                send_undo_block_via_server(base_dir,
 | 
						|
                                                           session_block,
 | 
						|
                                                           nickname, password,
 | 
						|
                                                           domain, port,
 | 
						|
                                                           http_prefix,
 | 
						|
                                                           block_actor,
 | 
						|
                                                           cached_webfingers,
 | 
						|
                                                           person_cache,
 | 
						|
                                                           False, __version__,
 | 
						|
                                                           sign_priv_key_pem)
 | 
						|
                refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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)
 | 
						|
                    else:
 | 
						|
                        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 = \
 | 
						|
                                    local_actor_url(http_prefix,
 | 
						|
                                                    block_nickname,
 | 
						|
                                                    block_domain)
 | 
						|
                if curr_index > 0 and box_json and not block_actor:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object and not block_actor:
 | 
						|
                    if post_json_object.get('id') and \
 | 
						|
                       post_json_object.get('object'):
 | 
						|
                        if has_object_dict(post_json_object):
 | 
						|
                            if post_json_object['object'].get('attributedTo'):
 | 
						|
                                block_actor = \
 | 
						|
                                    post_json_object['object']['attributedTo']
 | 
						|
                if block_actor:
 | 
						|
                    say_str = 'Blocking ' + \
 | 
						|
                        get_nickname_from_actor(block_actor)
 | 
						|
                    _say_command(say_str, say_str,
 | 
						|
                                 screenreader,
 | 
						|
                                 system_language, espeak)
 | 
						|
                    session_block = create_session(proxy_type)
 | 
						|
                    send_block_via_server(base_dir, session_block,
 | 
						|
                                          nickname, password,
 | 
						|
                                          domain, port,
 | 
						|
                                          http_prefix,
 | 
						|
                                          block_actor,
 | 
						|
                                          cached_webfingers,
 | 
						|
                                          person_cache,
 | 
						|
                                          False, __version__,
 | 
						|
                                          signing_priv_key_pem)
 | 
						|
                refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        unlike_actor = \
 | 
						|
                            post_json_object['object']['attributedTo']
 | 
						|
                        say_str = \
 | 
						|
                            'Undoing like of post by ' + \
 | 
						|
                            get_nickname_from_actor(unlike_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        session_unlike = create_session(proxy_type)
 | 
						|
                        send_undo_like_via_server(base_dir, session_unlike,
 | 
						|
                                                  nickname, password,
 | 
						|
                                                  domain, port, http_prefix,
 | 
						|
                                                  post_json_object['id'],
 | 
						|
                                                  cached_webfingers,
 | 
						|
                                                  person_cache,
 | 
						|
                                                  False, __version__,
 | 
						|
                                                  signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        post_id = post_json_object['id']
 | 
						|
                        announce_actor = \
 | 
						|
                            post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Announcing post by ' + \
 | 
						|
                            get_nickname_from_actor(announce_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        session_announce = create_session(proxy_type)
 | 
						|
                        send_announce_via_server(base_dir, session_announce,
 | 
						|
                                                 nickname, password,
 | 
						|
                                                 domain, port,
 | 
						|
                                                 http_prefix, post_id,
 | 
						|
                                                 cached_webfingers,
 | 
						|
                                                 person_cache,
 | 
						|
                                                 True, __version__,
 | 
						|
                                                 signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        post_id = post_json_object['id']
 | 
						|
                        announce_actor = \
 | 
						|
                            post_json_object['object']['attributedTo']
 | 
						|
                        say_str = 'Undoing announce post by ' + \
 | 
						|
                            get_nickname_from_actor(announce_actor)
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                        session_announce = create_session(proxy_type)
 | 
						|
                        send_undo_announce_via_server(base_dir,
 | 
						|
                                                      session_announce,
 | 
						|
                                                      post_json_object,
 | 
						|
                                                      nickname, password,
 | 
						|
                                                      domain, port,
 | 
						|
                                                      http_prefix, post_id,
 | 
						|
                                                      cached_webfingers,
 | 
						|
                                                      person_cache,
 | 
						|
                                                      True, __version__,
 | 
						|
                                                      signing_priv_key_pem)
 | 
						|
                        refresh_timeline = True
 | 
						|
                print('')
 | 
						|
            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 = \
 | 
						|
                    get_follow_requests_via_server(base_dir, session,
 | 
						|
                                                   nickname, password,
 | 
						|
                                                   domain, port,
 | 
						|
                                                   http_prefix, curr_page,
 | 
						|
                                                   cached_webfingers,
 | 
						|
                                                   person_cache,
 | 
						|
                                                   debug, __version__,
 | 
						|
                                                   signing_priv_key_pem)
 | 
						|
                if follow_requests_json:
 | 
						|
                    if isinstance(follow_requests_json, dict):
 | 
						|
                        _desktop_show_follow_requests(follow_requests_json,
 | 
						|
                                                      translate)
 | 
						|
                print('')
 | 
						|
            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 = \
 | 
						|
                    get_following_via_server(base_dir, session,
 | 
						|
                                             nickname, password,
 | 
						|
                                             domain, port,
 | 
						|
                                             http_prefix, curr_page,
 | 
						|
                                             cached_webfingers, person_cache,
 | 
						|
                                             debug, __version__,
 | 
						|
                                             signing_priv_key_pem)
 | 
						|
                if following_json:
 | 
						|
                    if isinstance(following_json, dict):
 | 
						|
                        _desktop_show_following(following_json, translate,
 | 
						|
                                                curr_page, indent,
 | 
						|
                                                'following')
 | 
						|
                print('')
 | 
						|
            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 = \
 | 
						|
                    get_followers_via_server(base_dir, session,
 | 
						|
                                             nickname, password,
 | 
						|
                                             domain, port,
 | 
						|
                                             http_prefix, curr_page,
 | 
						|
                                             cached_webfingers, person_cache,
 | 
						|
                                             debug, __version__,
 | 
						|
                                             signing_priv_key_pem)
 | 
						|
                if followers_json:
 | 
						|
                    if isinstance(followers_json, dict):
 | 
						|
                        _desktop_show_following(followers_json, translate,
 | 
						|
                                                curr_page, indent,
 | 
						|
                                                'followers')
 | 
						|
                print('')
 | 
						|
            elif (command_str == 'follow' or
 | 
						|
                  command_str.startswith('follow ')):
 | 
						|
                if command_str == 'follow':
 | 
						|
                    if actor_json:
 | 
						|
                        follow_handle = actor_json['id']
 | 
						|
                    else:
 | 
						|
                        follow_handle = ''
 | 
						|
                else:
 | 
						|
                    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,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                        session_follow = create_session(proxy_type)
 | 
						|
                        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:
 | 
						|
                        if follow_handle:
 | 
						|
                            say_str = follow_handle + ' is not valid'
 | 
						|
                        else:
 | 
						|
                            say_str = 'Specify a handle to follow'
 | 
						|
                        _say_command(say_str,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                    print('')
 | 
						|
            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,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                        session_unfollow = create_session(proxy_type)
 | 
						|
                        send_unfollow_request_via_server(base_dir,
 | 
						|
                                                         session_unfollow,
 | 
						|
                                                         nickname, password,
 | 
						|
                                                         domain, port,
 | 
						|
                                                         follow_nickname,
 | 
						|
                                                         follow_domain,
 | 
						|
                                                         follow_port,
 | 
						|
                                                         http_prefix,
 | 
						|
                                                         cached_webfingers,
 | 
						|
                                                         person_cache,
 | 
						|
                                                         debug, __version__,
 | 
						|
                                                         signing_priv_key_pem)
 | 
						|
                    else:
 | 
						|
                        say_str = follow_handle + ' is not valid'
 | 
						|
                        _say_command(say_str, say_str,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                    print('')
 | 
						|
            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,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                        session_approve = create_session(proxy_type)
 | 
						|
                        approve_follow_request_via_server(base_dir,
 | 
						|
                                                          session_approve,
 | 
						|
                                                          nickname, password,
 | 
						|
                                                          domain, port,
 | 
						|
                                                          http_prefix,
 | 
						|
                                                          approve_handle,
 | 
						|
                                                          cached_webfingers,
 | 
						|
                                                          person_cache,
 | 
						|
                                                          debug,
 | 
						|
                                                          __version__,
 | 
						|
                                                          signing_priv_key_pem)
 | 
						|
                    else:
 | 
						|
                        if approve_handle:
 | 
						|
                            say_str = approve_handle + ' is not valid'
 | 
						|
                        else:
 | 
						|
                            say_str = 'Specify a handle to approve'
 | 
						|
                        _say_command(say_str,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                    print('')
 | 
						|
            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,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                        session_deny = create_session(proxy_type)
 | 
						|
                        deny_follow_request_via_server(base_dir, session_deny,
 | 
						|
                                                       nickname, password,
 | 
						|
                                                       domain, port,
 | 
						|
                                                       http_prefix,
 | 
						|
                                                       deny_handle,
 | 
						|
                                                       cached_webfingers,
 | 
						|
                                                       person_cache,
 | 
						|
                                                       debug,
 | 
						|
                                                       __version__,
 | 
						|
                                                       signing_priv_key_pem)
 | 
						|
                    else:
 | 
						|
                        if deny_handle:
 | 
						|
                            say_str = deny_handle + ' is not valid'
 | 
						|
                        else:
 | 
						|
                            say_str = 'Specify a handle to deny'
 | 
						|
                        _say_command(say_str,
 | 
						|
                                     screenreader, system_language, espeak)
 | 
						|
                    print('')
 | 
						|
            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,
 | 
						|
                                 system_language, espeak,
 | 
						|
                                 name_str, gender)
 | 
						|
                    time.sleep(2)
 | 
						|
                    _say_command(content, message_str, screenreader,
 | 
						|
                                 system_language, espeak,
 | 
						|
                                 name_str, gender)
 | 
						|
                    print('')
 | 
						|
            elif command_str in ('sounds on',
 | 
						|
                                 'sound on',
 | 
						|
                                 'sound'):
 | 
						|
                say_str = 'Notification sounds on'
 | 
						|
                _say_command(say_str, say_str, screenreader,
 | 
						|
                             system_language, espeak)
 | 
						|
                notification_sounds = True
 | 
						|
            elif command_str in ('sounds off',
 | 
						|
                                 'sound off',
 | 
						|
                                 'nosound'):
 | 
						|
                say_str = 'Notification sounds off'
 | 
						|
                _say_command(say_str, say_str, screenreader,
 | 
						|
                             system_language, espeak)
 | 
						|
                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,
 | 
						|
                                 system_language, espeak)
 | 
						|
                else:
 | 
						|
                    print('No --screenreader option was specified')
 | 
						|
            elif command_str in ('mute',
 | 
						|
                                 'screen reader off',
 | 
						|
                                 'speaker off',
 | 
						|
                                 'talker off',
 | 
						|
                                 'reader off'):
 | 
						|
                if original_screen_reader:
 | 
						|
                    screenreader = None
 | 
						|
                    say_str = 'Screen reader off'
 | 
						|
                    _say_command(say_str, say_str, original_screen_reader,
 | 
						|
                                 system_language, espeak)
 | 
						|
                else:
 | 
						|
                    print('No --screenreader option was specified')
 | 
						|
            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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object['type'] == 'Announce':
 | 
						|
                        recent_posts_cache = {}
 | 
						|
                        allow_local_network_access = False
 | 
						|
                        yt_replace_domain = None
 | 
						|
                        twitter_replacement_domain = None
 | 
						|
                        post_json_object2 = \
 | 
						|
                            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,
 | 
						|
                                              blocked_cache,
 | 
						|
                                              bold_reading)
 | 
						|
                        if post_json_object2:
 | 
						|
                            post_json_object = post_json_object2
 | 
						|
                if post_json_object:
 | 
						|
                    content = \
 | 
						|
                        get_base_content_from_post(post_json_object,
 | 
						|
                                                   system_language)
 | 
						|
                    message_str, detected_links = \
 | 
						|
                        speakable_text(base_dir, content, translate)
 | 
						|
                    link_opened = False
 | 
						|
                    for url in detected_links:
 | 
						|
                        if '://' in url:
 | 
						|
                            webbrowser.open(url)
 | 
						|
                            link_opened = True
 | 
						|
                    if link_opened:
 | 
						|
                        say_str = 'Opened web links'
 | 
						|
                        _say_command(say_str, say_str, original_screen_reader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                    else:
 | 
						|
                        say_str = 'There are no web links to open.'
 | 
						|
                        _say_command(say_str, say_str, original_screen_reader,
 | 
						|
                                     system_language, espeak)
 | 
						|
                print('')
 | 
						|
            elif (command_str.startswith('pgp') or
 | 
						|
                  command_str.startswith('gpg')):
 | 
						|
                if not has_local_pg_pkey():
 | 
						|
                    print('No PGP public key was found')
 | 
						|
                else:
 | 
						|
                    print(pgp_local_public_key())
 | 
						|
                print('')
 | 
						|
            elif command_str.startswith('h'):
 | 
						|
                _desktop_help()
 | 
						|
                say_str = 'Press Enter to continue...'
 | 
						|
                say_str2 = _highlight_text(say_str)
 | 
						|
                _say_command(say_str2, say_str,
 | 
						|
                             screenreader, system_language, espeak)
 | 
						|
                input()
 | 
						|
                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:
 | 
						|
                    post_json_object = \
 | 
						|
                        _desktop_get_box_post_object(box_json, curr_index)
 | 
						|
                if post_json_object:
 | 
						|
                    if post_json_object.get('id'):
 | 
						|
                        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,
 | 
						|
                                         screenreader,
 | 
						|
                                         system_language, espeak)
 | 
						|
                        else:
 | 
						|
                            print('')
 | 
						|
                            if post_json_object['object'].get('summary'):
 | 
						|
                                print(post_json_object['object']['summary'])
 | 
						|
                            content_str = \
 | 
						|
                                get_base_content_from_post(post_json_object,
 | 
						|
                                                           system_language)
 | 
						|
                            print(content_str)
 | 
						|
                            print('')
 | 
						|
                            say_str = 'Confirm delete, yes or no?'
 | 
						|
                            _say_command(say_str, say_str, screenreader,
 | 
						|
                                         system_language, espeak)
 | 
						|
                            yesno = input()
 | 
						|
                            if 'y' not in yesno.lower():
 | 
						|
                                say_str = 'Deleting post'
 | 
						|
                                _say_command(say_str, say_str,
 | 
						|
                                             screenreader,
 | 
						|
                                             system_language, espeak)
 | 
						|
                                sessionrm = create_session(proxy_type)
 | 
						|
                                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)
 | 
						|
                                refresh_timeline = True
 | 
						|
                print('')
 | 
						|
 | 
						|
            if refresh_timeline:
 | 
						|
                if box_json:
 | 
						|
                    _desktop_show_box(indent, follow_requests_json,
 | 
						|
                                      your_actor, curr_timeline, box_json,
 | 
						|
                                      translate,
 | 
						|
                                      screenreader, system_language,
 | 
						|
                                      espeak, page_number,
 | 
						|
                                      new_replies_exist, new_dms_exist)
 |