forked from Murgeye/teamspeak3-python-bot
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmodule_loader.py
161 lines (135 loc) · 4.72 KB
/
module_loader.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# standard imports
import importlib
import logging
import sys
# local imports
from command_handler import CommandHandler
from event_handler import EventHandler
setups = []
exits = []
plugin_modules = {}
EVENT_HANDLER: "EventHandler"
COMMAND_HANDLER: "CommandHandler"
# configure logger
CLASS_NAME = "ModuleLoader"
logger = logging.getLogger(CLASS_NAME)
logger.propagate = 0
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler(f"logs/{CLASS_NAME.lower()}.log", mode="a+")
formatter = logging.Formatter("%(asctime)s: %(levelname)s: %(message)s")
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.info("Configured %s logger", str(CLASS_NAME))
logger.propagate = 0
# We really really want to catch all Exception here to prevent a bad module crashing the
# whole Bot
# noinspection PyBroadException,PyPep8
def load_modules(bot, config):
"""
Load modules specified in the Plugins section of config.ini.
:param bot: Bot to pass to the setup function of the modules
:param config: Main bot config with plugins section
"""
global EVENT_HANDLER, COMMAND_HANDLER
plugins = config.pop("Plugins")
EVENT_HANDLER = bot.event_handler
COMMAND_HANDLER = bot.command_handler
for plugin in plugins.items():
try:
plugin_modules[plugin[0]] = importlib.import_module(
f"modules.{plugin[1]}", package="modules"
)
plugin_modules[plugin[0]].pluginname = plugin[1]
logger.info("Loaded module %s", str(plugin[1]))
except ImportError:
logger.exception(
"Error while loading plugin %s from modules. %s",
str(plugin[0]),
str(plugin[1]),
)
raise
except KeyError:
logger.exception("Error while loading plugin from modules: %s", str(plugin))
raise
# Call all registered setup functions
for setup_func in setups:
try:
# `SomeModule` => `SomeModule`
plugin_name = sys.modules.get(setup_func.__module__).pluginname
if plugin_name.count(".") == 1:
# `SomeModule.main` => `SomeModule`
plugin_name = plugin_name.split(".")[0]
except AttributeError:
logger.exception("Error while setting up the module %s.", str(plugin_name))
raise
if plugin_name in config:
plugin_config = config.pop(plugin_name)
logger.info("%s plugin config: %s", str(plugin_name), str(plugin_config))
setup_func(ts3bot=bot, **plugin_config)
else:
logger.info(
"%s plugin config: Unconfigured, using plugin defaults.",
str(plugin_name),
)
setup_func(bot)
def setup_plugin(function):
"""
Decorator for registering the setup function of a module.
:param function: Function to register as setup
:return:
"""
setups.append(function)
return function
def event(*event_types):
"""
Decorator to register a function as an eventlistener for the event types specified in
event_types.
:param event_types: Event types to listen to
:type event_types: TS3Event
"""
def register_observer(function):
for event_type in event_types:
EVENT_HANDLER.add_observer(function, event_type)
return function
return register_observer
def command(*command_list):
"""
Decorator to register a function as a handler for text commands.
:param command_list: Commands to handle.
:type command_list: str
:return:
"""
def register_command(function):
for text_command in command_list:
COMMAND_HANDLER.add_handler(function, text_command)
return function
return register_command
def group(*groups):
"""
Decorator to specify which groups are allowed to use the commands specified for this function.
:param groups: List of server groups that are allowed to use the commands associated with this
function.
:type groups: str
"""
def save_allowed_groups(func):
func.allowed_groups = groups
return func
return save_allowed_groups
def exit_plugin(function):
"""
Decorator to mark a function to be called upon module exit.
:param function: Exit function to call.
"""
exits.append(function)
# We really really want to catch all Exception here to prevent a bad module preventing everything
# else from exiting
# noinspection PyBroadException
def exit_all():
"""
Exit all modules by calling their exit function.
"""
for exit_func in exits:
try:
exit_func()
except BaseException:
logger.exception("Error while exiting the module %s.", str(exit_func))