A Python Mastodon bot that's geared towards instance admins and their needs
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.8 KiB

#!/usr/bin/env python3
"""Various Toot help method for bots."""
import textwrap
from html.parser import HTMLParser
from mastodon import Mastodon
class MLStripper(HTMLParser):
"""Parser that removes HTML tags from input data."""
# From https://stackoverflow.com/questions/753052/strip-html-from-strings-in-python#925630
def __init__(self):
self.strict = False
self.convert_charrefs= True
self.fed = []
def handle_data(self, d):
def get_data(self):
return ''.join(self.fed)
class ArticleFormatter:
"""Provider properties suitable for passing into a string formatter."""
def __init__(self, article, *, mentions=None, username=None):
self._article = article
self._mentions = mentions
self._username = username
def abbreviated_content(self, length):
"""Return the stripped content shortened to `length` characters."""
return textwrap.shorten(self.stripped_content, length)
def content(self):
"""Return the article's raw content."""
return self._article.content[0]['value']
def mentions(self):
"""Return the formatted mentions (if any)."""
if self._mentions is None:
return ''
mentions_text = ''
for account in self._mentions:
mentions_text = mentions_text + ' @' + account['acct']
mentions_text = mentions_text.strip()
return mentions_text
def published(self):
"""Return the article's publication date."""
return self._article.published
def stripped_content(self):
"""Return the article's content, stripped of HTML."""
stripper = MLStripper()
return stripper.get_data()
def stripped_content_400(self):
"""Return the first 400 characters of the article's stripped content."""
return self.abbreviated_content(400)
def title(self):
"""Return the article's title."""
return self._article.title
def url(self):
"""Return the article's URL."""
return self._article.link
def username(self):
"""Return the Mastodon username."""
return self._username
def toot(config, article=None, username=None, in_reply_to=None, mentions=None):
"""Send a toot."""
# Setup Mastodon API
mastodon = Mastodon(
formatter = ArticleFormatter(article, mentions=mentions, username=username)
# Process main toot
cw_text = None
if 'cw_text' in config['toot']:
cw_text = config['toot']['cw_text'].format(formatter)
toot_text = config['toot']['toot_text'].format(formatter)
# Send main toot
parent_toot = mastodon.status_post(toot_text, visibility=config['toot']['visibility'],
spoiler_text=cw_text, in_reply_to_id=in_reply_to)
parent_toot_id = parent_toot['id']
# Handle any sub-toots
if 'subtoots' in config['toot']:
for subtoot in config['toot']['subtoots']:
cw_text = None
if 'cw_text' in subtoot:
cw_text = subtoot['cw_text'].format(formatter)
# Return the parent toot dict just in case it's needed elsewhere
return parent_toot