136 lines
4.0 KiB
Python
136 lines
4.0 KiB
Python
import logging
|
|
from abc import ABC, abstractmethod
|
|
|
|
from nio import RoomMessageText, MatrixRoom
|
|
|
|
class ModuleCannotBeDisabled(Exception):
|
|
pass
|
|
|
|
class BotModule(ABC):
|
|
"""Abtract bot module
|
|
|
|
A module derives from this class to process and interact on room messages. The subclass must be named `MatrixModule`.
|
|
Just write a python file with desired command name and place it in modules. See current modules for examples.
|
|
|
|
No need to register it anywhere else.
|
|
|
|
Example:
|
|
|
|
class MatrixModule(BotModule):
|
|
async def matrix_message(self, bot, room, event):
|
|
args = event.body.split()
|
|
args.pop(0)
|
|
|
|
# Echo what they said back
|
|
await bot.send_text(room, ' '.join(args))
|
|
|
|
def help(self):
|
|
return 'Echoes back what user has said'
|
|
|
|
"""
|
|
|
|
def __init__(self, name):
|
|
self.enabled = True
|
|
self.name = name
|
|
self.logger = logging.getLogger("module " + self.name)
|
|
|
|
def matrix_start(self, bot):
|
|
"""Called once on startup
|
|
|
|
:param bot: a reference to the bot
|
|
:type bot: Bot
|
|
"""
|
|
self.logger.info('Starting..')
|
|
|
|
@abstractmethod
|
|
async def matrix_message(self, bot, room, event):
|
|
"""Called when a message is sent to room starting with !module_name
|
|
|
|
:param bot: a reference to the bot
|
|
:type bot: Bot
|
|
:param room: a matrix room message
|
|
:type room: MatrixRoom
|
|
:param event: a handle to the event that triggered the callback
|
|
:type event: RoomMessageText
|
|
"""
|
|
pass
|
|
|
|
def matrix_stop(self, bot):
|
|
"""Called once before exit
|
|
|
|
:param bot: a reference to the bot
|
|
:type bot: Bot
|
|
"""
|
|
self.logger.info('Stopping..')
|
|
|
|
async def matrix_poll(self, bot, pollcount):
|
|
"""Called every 10 seconds
|
|
|
|
:param bot: a reference to the bot
|
|
:type bot: Bot
|
|
:param pollcount: the actual poll count
|
|
:type pollcount: int
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def help(self):
|
|
"""Return one-liner help text"""
|
|
return 'A cool hemppa module'
|
|
|
|
def long_help(self, bot=None, room=None, event=None, args=[]):
|
|
"""Return longer help text
|
|
|
|
Used by help module as !help modulename [args ...]
|
|
bot, room, and event are passed to allow a module
|
|
to give contextual help
|
|
|
|
If not defined, falls back to short help
|
|
"""
|
|
return self.help()
|
|
|
|
def get_settings(self):
|
|
"""Must return a dict object that can be converted to JSON and sent to server
|
|
|
|
:return: a dict object that can be converted to JSON
|
|
:rtype: dict
|
|
"""
|
|
return {'enabled': self.enabled,}
|
|
|
|
def set_settings(self, data):
|
|
"""Load these settings. It should be the same JSON you returned in previous get_settings
|
|
|
|
:param data: a dict object containing the settings read from the account
|
|
:type data: dict
|
|
"""
|
|
if data.get('enabled') is not None:
|
|
self.enabled = data['enabled']
|
|
|
|
def add_module_aliases(self, bot, args, force=False):
|
|
"""Add a list of aliases for this module.
|
|
|
|
:param args: a list of strings by which this module can be called
|
|
:type args: list
|
|
:param force: override any existing aliases
|
|
:type force: bool, optional
|
|
"""
|
|
for name in args:
|
|
if bot.modules.get(name):
|
|
self.logger.info(f"not aliasing {name}, it is already a module")
|
|
continue
|
|
prev = bot.module_aliases.get(name)
|
|
if prev == self.name:
|
|
continue
|
|
if prev and not force:
|
|
self.logger.info(f"not aliasing {name}, it is already an alias for {prev}")
|
|
continue
|
|
if prev:
|
|
self.logger.debug(f"overriding alias {name} for {prev}")
|
|
bot.module_aliases[name] = self.name
|
|
|
|
def enable(self):
|
|
self.enabled = True
|
|
|
|
def disable(self):
|
|
self.enabled = False
|