Release 0.9.0
This commit is contained in:
1
bot/mixins/__init__.py
Normal file
1
bot/mixins/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
__all__ = ["action", "template", "trigger", "widget"]
|
||||
106
bot/mixins/action.py
Normal file
106
bot/mixins/action.py
Normal file
@@ -0,0 +1,106 @@
|
||||
from os import path, listdir, pardir
|
||||
from importlib import import_module
|
||||
from threading import Thread
|
||||
from bot import loaded_modules_dict
|
||||
import string
|
||||
import random
|
||||
|
||||
|
||||
class Action(object):
|
||||
available_actions_dict = dict
|
||||
trigger_action_hook = object
|
||||
|
||||
def __init__(self):
|
||||
self.available_actions_dict = {}
|
||||
self.trigger_action_hook = self.trigger_action
|
||||
|
||||
def register_action(self, identifier, action_dict):
|
||||
self.available_actions_dict[identifier] = action_dict
|
||||
|
||||
def enable_action(self, identifier):
|
||||
self.available_actions_dict[identifier]["enabled"] = True
|
||||
|
||||
def disable_action(self, identifier):
|
||||
self.available_actions_dict[identifier]["enabled"] = False
|
||||
|
||||
@staticmethod
|
||||
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
|
||||
return ''.join(random.choice(chars) for _ in range(size))
|
||||
|
||||
@staticmethod
|
||||
def get_all_available_actions_dict():
|
||||
all_available_actions_dict = {}
|
||||
for loaded_module_identifier, loaded_module in loaded_modules_dict.items():
|
||||
if len(loaded_module.available_actions_dict) >= 1:
|
||||
all_available_actions_dict[loaded_module_identifier] = loaded_module.available_actions_dict
|
||||
|
||||
return all_available_actions_dict
|
||||
|
||||
def import_actions(self):
|
||||
modules_root_dir = path.join(path.dirname(path.abspath(__file__)), pardir, "modules")
|
||||
|
||||
module_actions_root_dir = path.join(modules_root_dir, self.options['module_name'], "actions")
|
||||
try:
|
||||
for module_action in listdir(module_actions_root_dir):
|
||||
if module_action == 'common.py' or module_action == '__init__.py' or module_action[-3:] != '.py':
|
||||
continue
|
||||
import_module("bot.modules." + self.options['module_name'] + ".actions." + module_action[:-3])
|
||||
except FileNotFoundError as error:
|
||||
# module does not have actions
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def trigger_action(target_module, event_data=None, dispatchers_steamid=None):
|
||||
if event_data is None:
|
||||
event_data = []
|
||||
action_identifier = event_data[0]
|
||||
if action_identifier in target_module.available_actions_dict:
|
||||
server_is_online = target_module.dom.data.get("module_telnet", {}).get("server_is_online", False)
|
||||
active_action = target_module.available_actions_dict[action_identifier]
|
||||
action_requires_server_to_be_online = active_action.get(
|
||||
"requires_telnet_connection", False
|
||||
)
|
||||
action_is_enabled = active_action.get("enabled", False)
|
||||
user_has_permission = event_data[1].get("has_permission", None)
|
||||
# permission is None = no status has been set, so it's allowed (default)
|
||||
# permission is True = Permission has been set by some other process
|
||||
# permission is False = permission has not been granted by any module
|
||||
|
||||
if dispatchers_steamid is not None:
|
||||
# none would be a system-call
|
||||
pass
|
||||
|
||||
if action_is_enabled:
|
||||
event_data[1]["module"] = target_module.getName()
|
||||
event_data[1]["uuid4"] = target_module.id_generator(22)
|
||||
if server_is_online is True or action_requires_server_to_be_online is not True:
|
||||
if any([
|
||||
user_has_permission is None,
|
||||
user_has_permission is True
|
||||
]):
|
||||
Thread(
|
||||
target=active_action.get("main_function"),
|
||||
args=(target_module, event_data, dispatchers_steamid)
|
||||
).start()
|
||||
else:
|
||||
# in case we don't have permission, we call the fail callback. it then can determine what to do
|
||||
# next
|
||||
fail_callback = active_action.get("callback_fail")
|
||||
Thread(
|
||||
target=target_module.callback_fail(
|
||||
fail_callback,
|
||||
target_module,
|
||||
event_data,
|
||||
dispatchers_steamid
|
||||
),
|
||||
args=(target_module, event_data, dispatchers_steamid)
|
||||
).start()
|
||||
else:
|
||||
try:
|
||||
skip_it_callback = active_action.get("skip_it")
|
||||
Thread(
|
||||
target=skip_it_callback,
|
||||
args=(target_module, event_data)
|
||||
).start()
|
||||
except KeyError:
|
||||
pass
|
||||
15
bot/mixins/template.py
Normal file
15
bot/mixins/template.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from os import path, pardir
|
||||
import jinja2
|
||||
|
||||
|
||||
class Template(object):
|
||||
templates = object
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def import_templates(self):
|
||||
modules_root_dir = path.join(path.dirname(path.abspath(__file__)), pardir, "modules")
|
||||
modules_template_dir = path.join(modules_root_dir, self.options['module_name'], 'templates')
|
||||
file_loader = jinja2.FileSystemLoader(modules_template_dir)
|
||||
self.templates = jinja2.Environment(loader=file_loader)
|
||||
62
bot/mixins/trigger.py
Normal file
62
bot/mixins/trigger.py
Normal file
@@ -0,0 +1,62 @@
|
||||
from bot import loaded_modules_dict
|
||||
from os import path, listdir, pardir
|
||||
from importlib import import_module
|
||||
import re
|
||||
|
||||
|
||||
class Trigger(object):
|
||||
available_triggers_dict = dict
|
||||
|
||||
def __init__(self):
|
||||
self.available_triggers_dict = {}
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
for name, triggers in self.available_triggers_dict.items():
|
||||
try:
|
||||
for trigger, handler in triggers["handlers"].items():
|
||||
self.dom.data.register_callback(self, trigger, handler)
|
||||
except KeyError:
|
||||
pass
|
||||
except KeyError as error:
|
||||
pass
|
||||
|
||||
def register_trigger(self, identifier, trigger_dict):
|
||||
self.available_triggers_dict[identifier] = trigger_dict
|
||||
|
||||
def import_triggers(self):
|
||||
modules_root_dir = path.join(path.dirname(path.abspath(__file__)), pardir, "modules")
|
||||
|
||||
module_triggers_root_dir = path.join(modules_root_dir, self.options['module_name'])
|
||||
try:
|
||||
for module_trigger in listdir(path.join(module_triggers_root_dir, "triggers")):
|
||||
if module_trigger == 'common.py' or module_trigger == '__init__.py' or module_trigger[-3:] != '.py':
|
||||
continue
|
||||
import_module("bot.modules." + self.options['module_name'] + ".triggers." + module_trigger[:-3])
|
||||
|
||||
for module_trigger in listdir(path.join(module_triggers_root_dir, "commands")):
|
||||
if module_trigger == 'common.py' or module_trigger == '__init__.py' or module_trigger[-3:] != '.py':
|
||||
continue
|
||||
import_module("bot.modules." + self.options['module_name'] + ".commands." + module_trigger[:-3])
|
||||
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
|
||||
def execute_telnet_triggers(self):
|
||||
telnet_lines_to_process = self.telnet.get_a_bunch_of_lines_from_queue(25)
|
||||
|
||||
for telnet_line in telnet_lines_to_process:
|
||||
for loaded_module in loaded_modules_dict.values():
|
||||
for trigger_name, trigger_group in loaded_module.available_triggers_dict.items():
|
||||
try:
|
||||
for trigger in trigger_group["triggers"]:
|
||||
regex_results = re.search(trigger["regex"], telnet_line)
|
||||
if regex_results:
|
||||
trigger["callback"](loaded_module, self, regex_results)
|
||||
# TODO: add method to append log, or create a new one
|
||||
# TODO: this needs to weed out triggers being called too often
|
||||
except KeyError:
|
||||
pass
|
||||
87
bot/mixins/widget.py
Normal file
87
bot/mixins/widget.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from os import path, listdir, pardir
|
||||
from importlib import import_module
|
||||
from bot import loaded_modules_dict
|
||||
|
||||
|
||||
class Widget(object):
|
||||
available_widgets_dict = dict
|
||||
template_render_hook = object
|
||||
|
||||
def __init__(self):
|
||||
self.available_widgets_dict = {}
|
||||
self.template_render_hook = self.template_render
|
||||
|
||||
def on_socket_connect(self, steamid):
|
||||
if isinstance(self.available_widgets_dict, dict) and len(self.available_widgets_dict) >= 1:
|
||||
for name, widget in self.available_widgets_dict.items():
|
||||
if widget["main_widget"] is not None:
|
||||
widget["main_widget"](self, dispatchers_steamid=steamid)
|
||||
|
||||
def on_socket_disconnect(self, steamid):
|
||||
if isinstance(self.available_widgets_dict, dict) and len(self.available_widgets_dict) >= 1:
|
||||
for name, widget in self.available_widgets_dict.items():
|
||||
if widget["main_widget"] is not None:
|
||||
widget["main_widget"](self, dispatchers_steamid=steamid)
|
||||
|
||||
def on_socket_event(self, event_data, dispatchers_steamid):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def template_render(*args, **kwargs):
|
||||
try:
|
||||
template = kwargs.get("template", None)
|
||||
rendered_template = template.render(**kwargs)
|
||||
except AttributeError as error:
|
||||
rendered_template = ""
|
||||
|
||||
return rendered_template
|
||||
|
||||
@staticmethod
|
||||
def get_all_available_widgets_dict():
|
||||
all_available_widgets_dict = {}
|
||||
for loaded_module_identifier, loaded_module in loaded_modules_dict.items():
|
||||
if len(loaded_module.available_widgets_dict) >= 1:
|
||||
all_available_widgets_dict[loaded_module_identifier] = loaded_module.available_widgets_dict
|
||||
|
||||
return all_available_widgets_dict
|
||||
|
||||
def start(self):
|
||||
if isinstance(self.available_widgets_dict, dict) and len(self.available_widgets_dict) >= 1:
|
||||
for name, widget in self.available_widgets_dict.items():
|
||||
for trigger, handler in widget["handlers"].items():
|
||||
self.dom.data.register_callback(self, trigger, handler)
|
||||
|
||||
def register_widget(self, identifier, widget_dict):
|
||||
if widget_dict.get("enabled", True):
|
||||
self.available_widgets_dict[identifier] = widget_dict
|
||||
|
||||
def import_widgets(self):
|
||||
modules_root_dir = path.join(path.dirname(path.abspath(__file__)), pardir, "modules")
|
||||
|
||||
module_widgets_root_dir = path.join(modules_root_dir, self.options['module_name'], "widgets")
|
||||
try:
|
||||
for module_widget in listdir(module_widgets_root_dir):
|
||||
if module_widget == 'common.py' or module_widget == '__init__.py' or module_widget[-3:] != '.py':
|
||||
continue
|
||||
import_module("bot.modules." + self.options['module_name'] + ".widgets." + module_widget[:-3])
|
||||
except FileNotFoundError as error:
|
||||
# module does not have widgets
|
||||
pass
|
||||
|
||||
def get_current_view(self, dispatchers_steamid):
|
||||
return (
|
||||
self.dom.data
|
||||
.get(self.get_module_identifier(), {})
|
||||
.get("visibility", {})
|
||||
.get(dispatchers_steamid, {})
|
||||
.get("current_view", "frontend")
|
||||
)
|
||||
|
||||
def set_current_view(self, dispatchers_steamid, options):
|
||||
self.dom.data.upsert({
|
||||
self.get_module_identifier(): {
|
||||
"visibility": {
|
||||
dispatchers_steamid: options
|
||||
}
|
||||
}
|
||||
}, dispatchers_steamid=dispatchers_steamid)
|
||||
Reference in New Issue
Block a user