106 lines
2.8 KiB
Python
Executable File
106 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Methods for loading modules.
|
|
"""
|
|
import os
|
|
import sys
|
|
import importlib
|
|
|
|
def load_module(bot, path):
|
|
"""
|
|
Loads a module from the provided path, cleans it up and registers
|
|
it with the bot's internal callable list.
|
|
"""
|
|
module = importlib.import_module(path)
|
|
if hasattr(module, 'setup'):
|
|
module.setup(bot)
|
|
relevant_parts = process_module(module, bot.config)
|
|
bot.register_callable(relevant_parts)
|
|
|
|
|
|
def unload_module(bot, name):
|
|
"""
|
|
Unloads a module and deletes references to it from the bot's memory.
|
|
"""
|
|
old_module = sys.modules[name]
|
|
|
|
# delete references to the module functions from the bot's memory
|
|
for obj_name, obj in vars(old_module).items():
|
|
bot.unregister_callable(obj)
|
|
|
|
del old_module
|
|
del sys.modules[name]
|
|
|
|
|
|
def find_modules(homedir):
|
|
"""
|
|
Searches through homedir/modules for python files and returns a dictionary
|
|
with the module name as the key and the path as the value.
|
|
"""
|
|
modules_dir = os.path.join(homedir, "modules")
|
|
modules = {}
|
|
for file in os.listdir(modules_dir):
|
|
if not file.endswith(".py"):
|
|
continue
|
|
name = file.replace(".py", "")
|
|
modules[name] = "modules" + "." + name
|
|
return modules
|
|
|
|
|
|
def process_module(module, config):
|
|
"""
|
|
Takes a module object and extracts relevant data objects out of it.
|
|
Returns all callables(read: functions) and shutdowns(?).
|
|
"""
|
|
callables = []
|
|
for key, obj in dict.items(vars(module)):
|
|
if callable(obj):
|
|
if is_triggerable(obj):
|
|
process_callable(obj, config)
|
|
callables.append(obj)
|
|
return callables
|
|
|
|
|
|
def is_triggerable(obj):
|
|
"""
|
|
Checks if the given function object is triggerable by Fulvia, eg. has
|
|
any of a few particular attributes or declarators defined.
|
|
"""
|
|
triggerable_attributes = ("commands", "hook", "url_callback")
|
|
return any(hasattr(obj, attr) for attr in triggerable_attributes)
|
|
|
|
|
|
def process_callable(func, config):
|
|
"""
|
|
Sets various helper atributes about a given function.
|
|
"""
|
|
prefix = config.core.prefix
|
|
doc = func.__doc__
|
|
if doc:
|
|
doc = doc.strip()
|
|
doc = doc.replace("\t", "")
|
|
doc = doc.replace("\n\n", "\x00")
|
|
doc = doc.replace("\n", " ")
|
|
doc = doc.replace("\x00", "\n")
|
|
func._docs = {}
|
|
|
|
func.example = getattr(func, "example", [(None, None)])
|
|
func.thread = getattr(func, 'thread', True)
|
|
func.hook = getattr(func, 'hook', False)
|
|
func.rate = getattr(func, 'rate', 0)
|
|
func.channel_rate = getattr(func, 'channel_rate', 0)
|
|
func.global_rate = getattr(func, 'global_rate', 0)
|
|
|
|
if hasattr(func, 'commands'):
|
|
if hasattr(func, 'example'):
|
|
for n, example in enumerate(func.example):
|
|
ex_input = example[0]
|
|
if not ex_input:
|
|
continue
|
|
if ex_input[0] != prefix:
|
|
ex_input = prefix + ex_input
|
|
func.example[n] = (ex_input, example[1])
|
|
if doc:
|
|
for command in func.commands:
|
|
func._docs[command] = (doc, func.example)
|