Simplify access to reblogged status data

Adds two properties to `Status` entity:
* `reblog` - contains the reblogged Status or None if not a reblog
* `original`- contains the reblogged Status or self if not a reblog

Anywhere where you wish to show a reblogged status's property when it's
a reblog, or the base status proprety if not a reblog, use
`status.original.<property>`.
This commit is contained in:
Ivan Habunek 2019-09-22 12:13:40 +02:00
parent bc6e43376a
commit 35e03a13b1
3 changed files with 75 additions and 35 deletions

View File

@ -226,7 +226,7 @@ class TUI(urwid.Frame):
# This is pretty fast, so it's probably ok to block while context is
# loaded, can be made async later if needed
context = api.context(self.app, self.user, status.id)
context = api.context(self.app, self.user, status.original.id)
ancestors = [self.make_status(s) for s in context["ancestors"]]
descendants = [self.make_status(s) for s in context["descendants"]]
statuses = ancestors + [status] + descendants
@ -337,7 +337,7 @@ class TUI(urwid.Frame):
promise.add_done_callback(lambda *args: self.close_overlay())
def show_media(self, status):
urls = [m["url"] for m in status.data["media_attachments"]]
urls = [m["url"] for m in status.original.data["media_attachments"]]
if urls:
show_media(urls)

View File

@ -2,7 +2,6 @@ from collections import namedtuple
from .utils import parse_datetime
Author = namedtuple("Author", ["account", "display_name"])
@ -11,8 +10,33 @@ class Status:
A wrapper around the Status entity data fetched from Mastodon.
https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md#status
Attributes
----------
reblog : Status or None
The reblogged status if it exists.
original : Status
If a reblog, the reblogged status, otherwise self.
"""
def __init__(self, data, is_mine, default_instance):
"""
Parameters
----------
data : dict
Status data as received from Mastodon.
https://docs.joinmastodon.org/api/entities/#status
is_mine : bool
Whether the status was created by the logged in user.
default_instance : str
The domain of the instance into which the user is logged in. Used to
create fully qualified account names for users on the same instance.
Mastodon only populates the name, not the domain.
"""
self.data = data
self.is_mine = is_mine
self.default_instance = default_instance
@ -20,34 +44,40 @@ class Status:
# This can be toggled by the user
self.show_sensitive = False
# TODO: make Status immutable?
# TODO: clean up
self.id = self.data["id"]
self.display_name = self.data["account"]["display_name"]
self.account = self.get_account()
self.account = self._get_account()
self.created_at = parse_datetime(data["created_at"])
self.author = self.get_author()
self.author = self._get_author()
self.favourited = data.get("favourited", False)
self.reblogged = data.get("reblogged", False)
self.in_reply_to = data.get("in_reply_to_id")
self.url = data.get("url")
self.mentions = data.get("mentions")
self.reblog = self._get_reblog()
self.reblog = reblog = data.get("reblog")
self.url = reblog.get("url") if reblog else data.get("url")
@property
def original(self):
return self.reblog or self
self.mentions = data["mentions"]
def get_author(self):
# Show the author, not the persopn who reblogged
data = self.data["reblog"] or self.data
acct = data['account']['acct']
acct = acct if "@" in acct else "{}@{}".format(acct, self.default_instance)
return Author(acct, data['account']['display_name'])
def get_account(self):
def _get_reblog(self):
reblog = self.data.get("reblog")
account = reblog['account'] if reblog else self.data['account']
acct = account['acct']
if not reblog:
return None
reblog_is_mine = self.is_mine and (
self.data["account"]["acct"] == reblog["account"]["acct"]
)
return Status(reblog, reblog_is_mine, self.default_instance)
def _get_author(self):
acct = self.data['account']['acct']
acct = acct if "@" in acct else "{}@{}".format(acct, self.default_instance)
return Author(acct, self.data['account']['display_name'])
def _get_account(self):
acct = self.data['account']['acct']
return acct if "@" in acct else "{}@{}".format(acct, self.default_instance)
def __repr__(self):
return "<Status id={}>".format(self.id)
return "<Status id={} account={}>".format(self.id, self.account)

View File

@ -136,7 +136,7 @@ class Timeline(urwid.Columns):
return
if key in ("s", "S"):
status.show_sensitive = True
status.original.show_sensitive = True
self.refresh_status_details()
return
@ -149,8 +149,8 @@ class Timeline(urwid.Columns):
return
if key in ("v", "V"):
if status.url:
webbrowser.open(status.url)
if status.original.url:
webbrowser.open(status.original.url)
return
return super().keypress(size, key)
@ -204,14 +204,24 @@ class Timeline(urwid.Columns):
class StatusDetails(urwid.Pile):
def __init__(self, status, in_thread):
"""
Parameters
----------
status : Status
The status to render.
in_thread : bool
Whether the status is rendered from a thread status list.
"""
self.in_thread = in_thread
widget_list = list(self.content_generator(status))
reblogged_by = status.author if status.reblog else None
widget_list = list(self.content_generator(status.original, reblogged_by))
return super().__init__(widget_list)
def content_generator(self, status):
if status.data["reblog"]:
boosted_by = status.data["account"]["display_name"]
yield ("pack", urwid.Text(("gray", "{} boosted".format(boosted_by))))
def content_generator(self, status, reblogged_by):
if reblogged_by:
text = "{} boosted".format(reblogged_by.display_name)
yield ("pack", urwid.Text(("gray", text)))
yield ("pack", urwid.AttrMap(urwid.Divider("-"), "gray"))
if status.author.display_name:
@ -315,10 +325,10 @@ class StatusDetails(urwid.Pile):
class StatusListItem(SelectableColumns):
def __init__(self, status):
created_at = status.created_at.strftime("%Y-%m-%d %H:%M")
favourited = ("yellow", "") if status.favourited else " "
reblogged = ("yellow", "") if status.reblogged else " "
favourited = ("yellow", "") if status.original.favourited else " "
reblogged = ("yellow", "") if status.original.reblogged else " "
is_reblog = ("cyan", "") if status.reblog else " "
is_reply = ("cyan", "") if status.in_reply_to else " "
is_reply = ("cyan", "") if status.original.in_reply_to else " "
return super().__init__([
("pack", SelectableText(("blue", created_at), wrap="clip")),
@ -327,7 +337,7 @@ class StatusListItem(SelectableColumns):
("pack", urwid.Text(" ")),
("pack", urwid.Text(reblogged)),
("pack", urwid.Text(" ")),
urwid.Text(("green", status.account), wrap="clip"),
urwid.Text(("green", status.original.account), wrap="clip"),
("pack", urwid.Text(is_reply)),
("pack", urwid.Text(is_reblog)),
("pack", urwid.Text(" ")),