Files
chrani-bot-tng/bot/module.py

104 lines
4.0 KiB
Python
Raw Normal View History

2025-11-21 07:26:02 +01:00
from threading import Thread, Event
from bot import started_modules_dict
from bot.logger import get_logger
from bot.mixins.trigger import Trigger
from bot.mixins.action import Action
from bot.mixins.template import Template
from bot.mixins.widget import Widget
logger = get_logger("module")
class Module(Thread, Action, Trigger, Template, Widget):
""" This class may ONLY be used to extend a module, it is not meant to be instantiated on it's own """
options = dict
stopped = object
run_observer_interval = int
run_observer_interval_idle = int
last_execution_time = float
def __init__(self):
if type(self) is Module:
raise NotImplementedError("You may not instantiate this class on it's own")
self.stopped = Event()
Action.__init__(self)
Trigger.__init__(self)
Template.__init__(self)
Widget.__init__(self)
Thread.__init__(self)
def setup(self, provided_options=dict):
self.options = self.default_options
options_filename = "module_" + self.options['module_name'] + ".json"
if isinstance(provided_options, dict):
self.options.update(provided_options)
logger.debug("module_options_loaded",
module=self.options['module_name'],
options_file=options_filename)
else:
logger.debug("module_options_defaults",
module=self.default_options["module_name"],
options_file=options_filename)
self.import_triggers()
self.import_actions()
self.import_templates()
self.import_widgets()
self.name = self.options['module_name']
return self
def start(self):
for required_module in self.required_modules:
setattr(self, required_module[7:], started_modules_dict[required_module])
setattr(self, self.name, self) # add self to dynamic module list to unify calls from actions
self.setDaemon(daemonic=True)
Thread.start(self)
Widget.start(self)
Trigger.start(self)
return self
def on_socket_connect(self, dispatchers_steamid):
Widget.on_socket_connect(self, dispatchers_steamid)
def on_socket_disconnect(self, dispatchers_steamid):
Widget.on_socket_disconnect(self, dispatchers_steamid)
def on_socket_event(self, event_data, dispatchers_steamid):
self.trigger_action_hook(self, event_data=event_data, dispatchers_steamid=dispatchers_steamid)
self.emit_event_status(self, event_data, dispatchers_steamid)
Widget.on_socket_event(self, event_data, dispatchers_steamid)
def emit_event_status(self, module, event_data, recipient_steamid, status=None):
# recipient_steamid can be None, "all" or [list_of_steamid's]
if recipient_steamid is not None and status is not None:
recipient_steamid = [recipient_steamid]
self.webserver.emit_event_status(module, event_data, recipient_steamid, status)
@staticmethod
def callback_success(callback, module, event_data, dispatchers_steamid, match=None):
event_data[1]["status"] = "success"
action_identifier = event_data[1]["action_identifier"]
if event_data[1].get("disable_after_success"):
module.disable_action(action_identifier)
module.emit_event_status(module, event_data, dispatchers_steamid, event_data[1])
callback(module, event_data, dispatchers_steamid, match)
@staticmethod
def callback_fail(callback, module, event_data, dispatchers_steamid):
event_data[1]["status"] = "fail"
logger.error("action_failed",
module=module.getName(),
action=event_data[0],
reason=event_data[1].get("fail_reason", "unknown"),
user=dispatchers_steamid)
module.emit_event_status(module, event_data, dispatchers_steamid, event_data[1])
callback(module, event_data, dispatchers_steamid)