wiki-postbot/wiki_postbot/clients/client.py

92 lines
2.8 KiB
Python

from abc import ABC, abstractmethod
from pathlib import Path
from wiki_postbot.interfaces.mediawiki import Wiki
from wiki_postbot.logger import init_logger
from wiki_postbot.patterns.wikilink import Wikilink
from typing import TYPE_CHECKING, List
if TYPE_CHECKING:
from logging import Logger
class Client(ABC):
"""
Metaclass for different clients (things that receive inputs like discord/slack messages)
pending some actual formalization of the concepts in this library (like idk what do we
call the wiki, a sink? idk)
Subclasses must implement all the abstract methods (that is, i guess, the definition
of abstract methods) but may do whatever other logic they need to do to handle messages,
eg. discord bot subclasses
"""
def __init__(
self,
wiki:Wiki,
name: str = "wikibot_client",
log_dir: Path = Path('/var/log/wikibot'),
):
super(Client, self).__init__()
self._wiki = None
self.wiki = wiki
self.name = name
self.log_dir = Path(log_dir)
self.logger = self._init_logger(name=self.name, log_dir=self.log_dir)
# --------------------------------------------------
# abstract methods
# --------------------------------------------------
# @abstractmethod
# def _react_progress(self, message):
# """React to a message indicating that we are processing it"""
# pass
# @abstractmethod
# def _react_complete(self, message):
# """React to a message indicating that we have completed processing it"""
# pass
# @abstractmethod
# def _react_error(self, message):
# """React to a message indicating there was some error"""
@abstractmethod
def parse_wikilinks(self, message) -> List[Wikilink]:
"""Parse a given message, returning the wikilinks it contains"""
@abstractmethod
def handle_wikilinks(self, message, wl: List[Wikilink]):
"""Handle the message with wikilinks, most likely by posting it to the wiki!"""
# --------------------------------------------------
# Properties
# --------------------------------------------------
@property
def wiki(self) -> Wiki:
return self._wiki
@wiki.setter
def wiki(self, wiki: Wiki):
if wiki.sess is None:
raise RuntimeError("Wiki client is not logged in! Login before passing to client")
self._wiki = wiki
# --------------------------------------------------
# Private methods
# --------------------------------------------------
def _init_logger(self, name:str, log_dir:Path) -> 'Logger':
# Try and make log directory, if we cant, it should fail.
log_dir.mkdir(exist_ok=True)
logger = init_logger(name=name, basedir=log_dir)
return logger