mirror of
https://github.com/ihabunek/toot.git
synced 2024-09-29 04:35:54 -04:00
Use entitites to simpliy print functions
This commit is contained in:
parent
a0b9b37a4f
commit
f3439ad30d
@ -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 == ""
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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]
|
||||||
|
|
||||||
|
|
||||||
|
104
toot/output.py
104
toot/output.py
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user