1
0
mirror of https://github.com/ihabunek/toot.git synced 2024-06-23 06:25:26 +00:00

Use entitites to simpliy print functions

This commit is contained in:
Ivan Habunek 2023-06-26 16:02:21 +02:00
parent a0b9b37a4f
commit f3439ad30d
No known key found for this signature in database
GPG Key ID: CDBD63C43A30BB95
4 changed files with 64 additions and 58 deletions

View File

@ -161,6 +161,7 @@ def test_timeline_with_re(mock_get, monkeypatch, capsys):
'acct': 'fz' 'acct': 'fz'
}, },
'reblog': { 'reblog': {
'created_at': '2017-04-12T15:53:18.174Z',
'account': { 'account': {
'display_name': 'Johnny Cash', 'display_name': 'Johnny Cash',
'acct': 'jc' 'acct': 'jc'
@ -179,8 +180,8 @@ def test_timeline_with_re(mock_get, monkeypatch, capsys):
out, err = capsys.readouterr() out, err = capsys.readouterr()
lines = uncolorize(out).split("\n") lines = uncolorize(out).split("\n")
assert "Frank Zappa" in lines[1] assert "Johnny Cash" in lines[1]
assert "@fz" in lines[1] assert "@jc" in lines[1]
assert "2017-04-12 15:53 UTC" in lines[1] assert "2017-04-12 15:53 UTC" in lines[1]
assert ( assert (
@ -188,7 +189,7 @@ def test_timeline_with_re(mock_get, monkeypatch, capsys):
"exact mathematical design, but\nwhat's missing is the eyebrows." in out) "exact mathematical design, but\nwhat's missing is the eyebrows." in out)
assert "111111111111111111" in lines[-3] assert "111111111111111111" in lines[-3]
assert "Reblogged @jc" in lines[-3] assert "@fz boosted" in lines[-3]
assert err == "" assert err == ""

View File

@ -6,6 +6,7 @@ from datetime import datetime, timedelta, timezone
from time import sleep, time from time import sleep, time
from toot import api, config, __version__ from toot import api, config, __version__
from toot.auth import login_interactive, login_browser_interactive, create_app_interactive from toot.auth import login_interactive, login_browser_interactive, create_app_interactive
from toot.entities import Instance, Notification, Status, from_dict
from toot.exceptions import ApiError, ConsoleError from toot.exceptions import ApiError, ConsoleError
from toot.output import (print_lists, print_out, print_instance, print_account, print_acct_list, from toot.output import (print_lists, print_out, print_instance, print_account, print_acct_list,
print_search_results, print_timeline, print_notifications, print_tag_list, print_search_results, print_timeline, print_notifications, print_tag_list,
@ -56,7 +57,8 @@ def timeline(app, user, args, generator=None):
if args.reverse: if args.reverse:
items = reversed(items) items = reversed(items)
print_timeline(items) statuses = [from_dict(Status, item) for item in items]
print_timeline(statuses)
if args.once or not sys.stdout.isatty(): if args.once or not sys.stdout.isatty():
break break
@ -78,7 +80,8 @@ def thread(app, user, args):
for item in context['descendants']: for item in context['descendants']:
thread.append(item) thread.append(item)
print_timeline(thread) statuses = [from_dict(Status, s) for s in thread]
print_timeline(statuses)
def post(app, user, args): def post(app, user, args):
@ -515,6 +518,7 @@ def instance(app, user, args):
try: try:
instance = api.get_instance(base_url) instance = api.get_instance(base_url)
instance = from_dict(Instance, instance)
print_instance(instance) print_instance(instance)
except ApiError: except ApiError:
raise ConsoleError( raise ConsoleError(
@ -542,6 +546,7 @@ def notifications(app, user, args):
if args.reverse: if args.reverse:
notifications = reversed(notifications) notifications = reversed(notifications)
notifications = [from_dict(Notification, n) for n in notifications]
print_notifications(notifications) print_notifications(notifications)

View File

@ -352,7 +352,7 @@ class Instance:
approval_required: bool approval_required: bool
invites_enabled: bool invites_enabled: bool
configuration: InstanceConfiguration configuration: InstanceConfiguration
contact_account: Account contact_account: Optional[Account]
rules: List[Rule] rules: List[Rule]

View File

@ -3,12 +3,11 @@ import re
import sys import sys
import textwrap import textwrap
from typing import List from toot.entities import Instance, Notification, Poll, Status
from wcwidth import wcswidth
from toot.tui.utils import parse_datetime
from toot.utils import get_text, parse_html from toot.utils import get_text, parse_html
from toot.wcstring import wc_wrap from toot.wcstring import wc_wrap
from typing import List
from wcwidth import wcswidth
STYLES = { STYLES = {
@ -136,25 +135,23 @@ def print_err(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs) print(*args, file=sys.stderr, **kwargs)
def print_instance(instance): def print_instance(instance: Instance):
print_out(f"<green>{instance['title']}</green>") print_out(f"<green>{instance.title}</green>")
print_out(f"<blue>{instance['uri']}</blue>") print_out(f"<blue>{instance.uri}</blue>")
print_out(f"running Mastodon {instance['version']}") print_out(f"running Mastodon {instance.version}")
print_out() print_out()
description = instance.get("description") if instance.description:
if description: for paragraph in re.split(r"[\r\n]+", instance.description.strip()):
for paragraph in re.split(r"[\r\n]+", description.strip()):
paragraph = get_text(paragraph) paragraph = get_text(paragraph)
print_out(textwrap.fill(paragraph, width=80)) print_out(textwrap.fill(paragraph, width=80))
print_out() print_out()
rules = instance.get("rules") if instance.rules:
if rules:
print_out("Rules:") print_out("Rules:")
for ordinal, rule in enumerate(rules): for ordinal, rule in enumerate(instance.rules):
ordinal = f"{ordinal + 1}." ordinal = f"{ordinal + 1}."
lines = textwrap.wrap(rule["text"], 80 - len(ordinal)) lines = textwrap.wrap(rule.text, 80 - len(ordinal))
first = True first = True
for line in lines: for line in lines:
if first: if first:
@ -162,6 +159,11 @@ def print_instance(instance):
first = False first = False
else: else:
print_out(f"{' ' * len(ordinal)} {line}") print_out(f"{' ' * len(ordinal)} {line}")
print_out()
contact = instance.contact_account
if contact:
print_out(f"Contact: {contact.display_name} @{contact.acct}")
def print_account(account): def print_account(account):
@ -269,20 +271,18 @@ def print_search_results(results):
print_out("<yellow>Nothing found</yellow>") print_out("<yellow>Nothing found</yellow>")
def print_status(status, width): def print_status(status: Status, width: int):
reblog = status['reblog'] status_id = status.id
content = reblog['content'] if reblog else status['content'] in_reply_to_id = status.in_reply_to_id
media_attachments = reblog['media_attachments'] if reblog else status['media_attachments'] reblogged_by = status.account if status.reblog else None
in_reply_to = status['in_reply_to_id']
poll = reblog.get('poll') if reblog else status.get('poll')
time = parse_datetime(status['created_at']) status = status.original
time = time.strftime('%Y-%m-%d %H:%M %Z')
username = "@" + status['account']['acct'] time = status.created_at.strftime('%Y-%m-%d %H:%M %Z')
username = "@" + status.account.acct
spacing = width - wcswidth(username) - wcswidth(time) - 2 spacing = width - wcswidth(username) - wcswidth(time) - 2
display_name = status['account']['display_name'] display_name = status.account.display_name
if display_name: if display_name:
spacing -= wcswidth(display_name) + 1 spacing -= wcswidth(display_name) + 1
@ -294,23 +294,24 @@ def print_status(status, width):
) )
print_out("") print_out("")
print_html(content, width) print_html(status.content, width)
if media_attachments: if status.media_attachments:
print_out("\nMedia:") print_out("\nMedia:")
for attachment in media_attachments: for attachment in status.media_attachments:
url = attachment["url"] url = attachment.url
for line in wc_wrap(url, width): for line in wc_wrap(url, width):
print_out(line) print_out(line)
if poll: if status.poll:
print_poll(poll) print_poll(status.poll)
print_out() print_out()
print_out( print_out(
f"ID <yellow>{status['id']}</yellow> ", f"ID <yellow>{status_id}</yellow> ",
f"↲ In reply to <yellow>{in_reply_to}</yellow> " if in_reply_to else "", f"↲ In reply to <yellow>{in_reply_to_id}</yellow> " if in_reply_to_id else "",
f"Reblogged <blue>@{reblog['account']['acct']}</blue> " if reblog else "", f"<blue>@{reblogged_by.acct}</blue> boosted " if reblogged_by else "",
) )
@ -325,33 +326,33 @@ def print_html(text, width=80):
first = False first = False
def print_poll(poll): def print_poll(poll: Poll):
print_out() print_out()
for idx, option in enumerate(poll["options"]): for idx, option in enumerate(poll.options):
perc = (round(100 * option["votes_count"] / poll["votes_count"]) perc = (round(100 * option.votes_count / poll.votes_count)
if poll["votes_count"] else 0) if poll.votes_count and option.votes_count is not None else 0)
if poll["voted"] and poll["own_votes"] and idx in poll["own_votes"]: if poll.voted and poll.own_votes and idx in poll.own_votes:
voted_for = " <yellow>✓</yellow>" voted_for = " <yellow>✓</yellow>"
else: else:
voted_for = "" voted_for = ""
print_out(f'{option["title"]} - {perc}% {voted_for}') print_out(f'{option.title} - {perc}% {voted_for}')
poll_footer = f'Poll · {poll["votes_count"]} votes' poll_footer = f'Poll · {poll.votes_count} votes'
if poll["expired"]: if poll.expired:
poll_footer += " · Closed" poll_footer += " · Closed"
if poll["expires_at"]: if poll.expires_at:
expires_at = parse_datetime(poll["expires_at"]).strftime("%Y-%m-%d %H:%M") expires_at = poll.expires_at.strftime("%Y-%m-%d %H:%M")
poll_footer += f" · Closes on {expires_at}" poll_footer += f" · Closes on {expires_at}"
print_out() print_out()
print_out(poll_footer) print_out(poll_footer)
def print_timeline(items, width=100): def print_timeline(items: list[Status], width=100):
print_out("" * width) print_out("" * width)
for item in items: for item in items:
print_status(item, width) print_status(item, width)
@ -366,20 +367,19 @@ notification_msgs = {
} }
def print_notification(notification, width=100): def print_notification(notification: Notification, width=100):
account = "{display_name} @{acct}".format(**notification["account"]) account = f"{notification.account.display_name} @{notification.account.acct}"
msg = notification_msgs.get(notification["type"]) msg = notification_msgs.get(notification.type)
if msg is None: if msg is None:
return return
print_out("" * width) print_out("" * width)
print_out(msg.format(account=account)) print_out(msg.format(account=account))
status = notification.get("status") if notification.status:
if status is not None: print_status(notification.status, width)
print_status(status, width)
def print_notifications(notifications, width=100): def print_notifications(notifications: list[Notification], width=100):
for notification in notifications: for notification in notifications:
print_notification(notification) print_notification(notification)
print_out("" * width) print_out("" * width)