diff --git a/zulip/tootbot.py b/zulip/tootbot.py index 687f46e..442c5f9 100644 --- a/zulip/tootbot.py +++ b/zulip/tootbot.py @@ -1,7 +1,8 @@ import argh import yaml -from mastodon import Mastodon +import mastodon +from bs4 import BeautifulSoup import zulip @@ -36,13 +37,137 @@ def format_status(status): if reblog is not None: boostee = format_account(reblog["account"]) boost_url = reblog["url"] - content = format_content(reblog["content"]) + content = format_content(reblog) return f"{sender} reblogged {boostee}'s [post]({boost_url})\n{content}" - return f"{" + content = format_content(status) + if reply: + return f"{sender} [replied]({url}) to message {reply}:\n{content}" -class Listener(Mastodon.StreamListener): + return f"{sender} [posted]({url}):\n{content}" + + +def md_wrap(kind, inner): + """ + Wrap inner in a markdown block with given kind, eg. "quote" or "spoiler TEXT HERE" + """ + return "\n".join([ + f"```{kind}", + inner, + "```", + ]) + + +def format_content(status): + # Main status text should be rendered into text and quoted + html = BeautifulSoup(status["content"], "html.parser") + text = html_to_md(html) + parts = [md_wrap("quote", text)] + # Append attachments, with the link name being the alt text. + # For images at least, zulip will auto-preview them. + for attachment in status["media_attachments"]: + type = attachment["type"] + description = attachment["description"] or "(no description provided)" + url = attachment["url"] + parts.append(f"Attached {type}: [{description}]({url})") + output = "\n".join(parts) + # If content warnings present, wrap in a spoiler block. + warning = status["spoiler_text"] + if warning: + output = md_wrap(f"spoiler {warning}", output) + return output + + +def html_to_md(html): + """ + Take a status HTML as a BeautifulSoup object + and make a best-effort attempt to render it in markdown: + * Convert each