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.

132 lines
3.8 KiB

4 years ago
#!/usr/bin/env python3
4 years ago
"""Various Toot help method for bots."""
4 years ago
import textwrap
from html.parser import HTMLParser
4 years ago
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):
super().__init__()
self.reset()
self.strict = False
self.convert_charrefs= True
self.fed = []
def handle_data(self, d):
self.fed.append(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)
@property
def content(self):
"""Return the article's raw content."""
return self._article.content[0]['value']
@property
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
@property
def published(self):
"""Return the article's publication date."""
return self._article.published
@property
def stripped_content(self):
"""Return the article's content, stripped of HTML."""
stripper = MLStripper()
stripper.feed(self.content)
return stripper.get_data()
@property
def stripped_content_400(self):
"""Return the first 400 characters of the article's stripped content."""
return self.abbreviated_content(400)
@property
def title(self):
"""Return the article's title."""
return self._article.title
@property
def url(self):
"""Return the article's URL."""
return self._article.link
@property
def username(self):
"""Return the Mastodon username."""
return self._username
def toot(config, article=None, username=None, in_reply_to=None, mentions=None):
4 years ago
"""Send a toot."""
4 years ago
# Setup Mastodon API
mastodon = Mastodon(
client_id=config['config']['client_cred_file'],
access_token=config['config']['user_cred_file'],
api_base_url=config['config']['api_base_url']
)
formatter = ArticleFormatter(article, mentions=mentions, username=username)
4 years ago
# 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)
4 years ago
# 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)
4 years ago
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)
4 years ago
mastodon.status_post(
subtoot['toot_text'].format(formatter),
4 years ago
in_reply_to_id=parent_toot_id,
visibility=subtoot['visibility'],
spoiler_text=cw_text
)
# Return the parent toot dict just in case it's needed elsewhere
return parent_toot