maidbot/main.py

142 lines
3.5 KiB
Python

import logging
import json
import os
import time
from datetime import datetime, timezone
from html.parser import HTMLParser
from mastodon import Mastodon
import mods.elicense
class Handler:
def __init__(self, app, st):
self.logging = logging.getLogger("app.handler")
self.app = app
self.st = st
self.text = sanitize_html(st["content"])
self.tokens = self.text.split()[1:]
self.handle()
def handle(self):
if self.tokens[0] == "watch":
self.watch()
else:
raise Exception("unknown command")
def watch(self):
date = self.tokens[1]
slots = [int(x) for x in self.tokens[2:]]
elapsed = datetime.now(timezone.utc) - self.st["created_at"]
if elapsed.seconds < self.app.CONFIG["interval"]:
self.app.reply(self.st, "accepted")
mod = self.app.mods["elicense"]
mod.watch(date, slots, lambda: self.app.reply(self.st, "reservation made"))
class App:
def __init__(self):
logging.basicConfig()
self.logging = logging.getLogger("app")
self.logging.setLevel(logging.DEBUG)
with open("config.json", "r") as f:
self.CONFIG = json.load(f)
self.logging.info("configuration loaded")
self.M = self.authenticate()
self.logging.info("authentication succeeded")
self.mods = {}
def authenticate(self):
if os.path.exists("auth.json"):
with open("auth.json", "r") as f:
auth = json.load(f)
M = Mastodon(
api_base_url = self.CONFIG["instance"],
client_id = auth["client_id"],
client_secret = auth["secret"],
access_token = auth["token"])
else:
cid, secret = Mastodon.create_app(
client_name = "maidbot",
api_base_url = self.CONFIG["instance"])
M = Mastodon(
client_id = cid,
client_secret = secret,
api_base_url = self.CONFIG["instance"])
tok = M.log_in(
username = self.CONFIG["username"],
password = self.CONFIG["password"])
dic = {"client_id": cid, "secret": secret, "token": tok}
with open("auth.json", "w") as f:
json.dump(dic, f, indent = 2)
return M
def install(self, name, mod):
self.logging.info("mod installed, "+name)
logger = logging.getLogger("mod."+name)
self.mods[name] = mod.init(self.CONFIG["mods"][name], logger)
def run(self):
self.install("elicense", mods.elicense)
while True:
try:
self.cycle()
self.logging.debug("cycle done")
except Exception as e:
self.logging.warning("cycle aborted:", e)
for mod in self.mods:
self.mods[mod].cycle()
time.sleep(self.CONFIG["interval"])
def cycle(self):
items = self.M.notifications(
account_id = self.CONFIG["master"],
types = "mention")
for item in items:
st = item["status"]
try:
Handler(self, st)
except Exception as e:
self.reply(st, "handling aborted: {}".format(e))
self.M.notifications_dismiss(id = item["id"])
# TODO: call mod cycles
def reply(self, st, msg):
try:
self.logging.debug("reply:", msg)
#self.M.status_post(
# status = "@{} {}".format(st["account"]["acct"], msg),
# in_reply_to_id = st["id"])
except Exception as e:
self.logging.error("reply failure:", msg, "(", e, ")")
def sanitize_html(html):
class F(HTMLParser):
text = ""
def handle_starttag(self, tag, attrs):
if tag == "br": self.text += " "
def handle_data(self, data):
self.text += data
f = F()
f.feed(html)
return f.text
App().run()