92 lines
2.5 KiB
Python
92 lines
2.5 KiB
Python
import feedparser
|
|
import json
|
|
from markdownify import markdownify
|
|
from mastodon import Mastodon
|
|
import re
|
|
import sys
|
|
import time
|
|
|
|
|
|
def process_html(html: str) -> str:
|
|
return re.sub(r"\n{3,}", "\n\n",
|
|
re.sub(r"\\(\W)", r"\1", re.sub(r"^(\s*)\* ", r"\1- ", markdownify(html), 0, re.MULTILINE))).strip()
|
|
|
|
|
|
def split_notes(text: str, limit: int) -> list[str]:
|
|
if len(text) <= limit:
|
|
return [text]
|
|
|
|
notes = []
|
|
|
|
prev = 0
|
|
while len(text[prev:prev + limit]) >= limit:
|
|
sub = text[prev:prev + limit]
|
|
|
|
i = sub.rfind("\n")
|
|
if i == -1:
|
|
i = sub.rfind(" ")
|
|
|
|
notes.append(sub[:i].strip())
|
|
prev += i + 1
|
|
|
|
return notes
|
|
|
|
|
|
def post_note(client: Mastodon, content: str, in_reply_to_id: str | None) -> str:
|
|
note = client.status_post(content, in_reply_to_id, visibility="unlisted")
|
|
print("Posted:", note["url"])
|
|
return note["id"]
|
|
|
|
|
|
def post_notes(client: Mastodon, notes: list[str]):
|
|
ids = []
|
|
for note in notes:
|
|
in_reply_to_id = ids[-1] if len(ids) != 0 else None
|
|
posted_note = post_note(client, note, in_reply_to_id)
|
|
ids.append(posted_note)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) < 3:
|
|
print("Usage:", sys.argv[0], "<account> <config>")
|
|
exit(1)
|
|
|
|
account = sys.argv[1]
|
|
config_path = sys.argv[2]
|
|
|
|
client = Mastodon(access_token=f"accounts/{account}.secret")
|
|
creds = client.account_verify_credentials()
|
|
print(f"Logged in:", creds["display_name"], "(@" + creds["fqn"] + ")")
|
|
instance = client.instance()
|
|
char_limit = instance["configuration"]["statuses"]["max_characters"]
|
|
|
|
config_file = open(config_path, "r")
|
|
config = json.load(config_file)
|
|
config_file.close()
|
|
|
|
for url in config.keys():
|
|
print("Updating", url)
|
|
rss = feedparser.parse(url)
|
|
|
|
rss.entries.sort(key=lambda entry: entry.published_parsed)
|
|
|
|
if config[url] is None:
|
|
config[url] = 0.0
|
|
if time.mktime(rss.entries[-1].published_parsed) <= config[url]:
|
|
continue
|
|
|
|
for entry in rss.entries:
|
|
if time.mktime(entry.published_parsed) <= config[url]:
|
|
continue
|
|
|
|
notes = split_notes("[" + entry.title + "](" + entry.link + ")\n" + process_html(
|
|
entry.content[0].value), char_limit)
|
|
|
|
post_notes(client, notes)
|
|
|
|
config[url] = time.mktime(rss.entries[-1].published_parsed)
|
|
|
|
print("Saving config", config)
|
|
config_file = open(config_path, "w")
|
|
json.dump(config, config_file, indent=4)
|
|
config_file.close()
|