Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/core/loader/__init__.py

195 lines
7.2 KiB
Python
Raw Normal View History

2021-02-01 15:13:11 +00:00
import importlib
import os
import re
2023-01-26 07:31:13 +00:00
import sys
2023-01-28 05:53:11 +00:00
import traceback
2021-11-12 14:25:53 +00:00
from typing import Dict, Union
2021-02-01 15:13:11 +00:00
2023-02-05 14:33:33 +00:00
from core.builtins import PrivateAssets
2021-08-07 07:56:48 +00:00
from core.logger import Logger
2023-02-05 14:33:33 +00:00
from core.types import Command, Schedule, RegexCommand, StartUp
2021-02-03 14:43:24 +00:00
load_dir_path = os.path.abspath('./modules/')
2021-02-03 14:43:24 +00:00
2021-07-07 16:00:24 +00:00
def load_modules():
2021-10-14 15:18:47 +00:00
err_prompt = []
2021-07-07 16:00:24 +00:00
fun_file = None
dir_list = os.listdir(load_dir_path)
for file_name in dir_list:
try:
2022-08-16 18:52:46 +00:00
file_path = os.path.join(load_dir_path, file_name)
fun_file = None
2021-04-07 15:18:41 +00:00
if os.path.isdir(file_path):
2022-04-23 14:22:56 +00:00
if file_name[0] != '_':
2021-04-07 15:18:41 +00:00
fun_file = file_name
2022-08-16 18:52:46 +00:00
elif os.path.isfile(file_path):
if file_name[0] != '_' and file_name.endswith('.py'):
fun_file = file_name[:-3]
2021-07-06 18:00:26 +00:00
if fun_file is not None:
2021-07-07 16:00:24 +00:00
Logger.info(f'Loading modules.{fun_file}...')
2021-07-06 18:00:26 +00:00
modules = 'modules.' + fun_file
importlib.import_module(modules)
2021-07-07 16:00:24 +00:00
Logger.info(f'Succeeded loaded modules.{fun_file}!')
except:
tb = traceback.format_exc()
errmsg = f'Failed to load modules.{fun_file}: \n{tb}'
2022-08-04 07:52:42 +00:00
Logger.error(errmsg)
err_prompt.append(errmsg)
2021-10-14 15:18:47 +00:00
loadercache = os.path.abspath(PrivateAssets.path + '/.cache_loader')
openloadercache = open(loadercache, 'w')
if err_prompt:
err_prompt = re.sub(r' File \"<frozen importlib.*?>\", .*?\n', '', '\n'.join(err_prompt))
openloadercache.write(err_prompt)
2021-10-14 15:18:47 +00:00
else:
openloadercache.write('')
2021-10-14 15:18:47 +00:00
openloadercache.close()
2021-07-07 16:00:24 +00:00
2021-08-07 07:56:48 +00:00
2021-07-09 09:35:23 +00:00
class ModulesManager:
2022-07-01 14:14:26 +00:00
modules: Dict[str, Union[Command, Schedule, RegexCommand, StartUp]] = {}
2023-01-28 05:53:11 +00:00
modulesOrigin: Dict[str, str] = {}
2021-07-07 16:00:24 +00:00
2021-08-30 18:53:39 +00:00
@staticmethod
2023-01-28 05:53:11 +00:00
def add_module(module: Union[Command, Schedule, RegexCommand, StartUp], py_module_name: str):
2021-10-24 10:55:45 +00:00
if module.bind_prefix not in ModulesManager.modules:
ModulesManager.modules.update({module.bind_prefix: module})
2023-01-26 13:21:46 +00:00
ModulesManager.modulesOrigin.update({module.bind_prefix: py_module_name})
2021-10-24 10:55:45 +00:00
else:
raise ValueError(f'Duplicate bind prefix "{module.bind_prefix}"')
2021-07-07 16:00:24 +00:00
2023-01-26 07:31:13 +00:00
@staticmethod
2023-01-26 13:21:46 +00:00
def remove_modules(modules):
for module in modules:
if module in ModulesManager.modules:
Logger.info(f'Removing...{module}')
ModulesManager.modules.pop(module)
ModulesManager.modulesOrigin.pop(module)
else:
raise ValueError(f'Module "{module}" is not exist')
2023-01-26 07:31:13 +00:00
2023-01-26 13:21:46 +00:00
@staticmethod
2023-01-28 05:53:11 +00:00
def search_related_module(module, includeSelf=True):
2023-01-26 13:21:46 +00:00
if module in ModulesManager.modulesOrigin:
modules = []
py_module = ModulesManager.return_py_module(module)
for m in ModulesManager.modulesOrigin:
if ModulesManager.modulesOrigin[m].startswith(py_module):
modules.append(m)
if not includeSelf:
modules.remove(module)
return modules
else:
raise ValueError(f'Could not find "{module}" in modulesOrigin dict')
2023-01-28 05:53:11 +00:00
2023-01-26 13:21:46 +00:00
@staticmethod
def return_py_module(module):
if module in ModulesManager.modulesOrigin:
2023-01-27 09:26:05 +00:00
return re.match(r'^modules(\.[a-zA-Z0-9_]*)?', ModulesManager.modulesOrigin[module]).group()
2023-01-26 13:21:46 +00:00
else:
return None
2023-01-28 05:53:11 +00:00
2021-08-30 18:53:39 +00:00
@staticmethod
2021-10-24 10:55:45 +00:00
def bind_to_module(bind_prefix: str, meta):
if bind_prefix in ModulesManager.modules:
ModulesManager.modules[bind_prefix].match_list.add(meta)
2021-02-01 15:13:11 +00:00
2021-08-30 18:53:39 +00:00
@staticmethod
2022-07-31 08:33:20 +00:00
def return_modules_list_as_dict(targetFrom: str = None) -> \
Dict[str, Union[Command, RegexCommand, Schedule, StartUp]]:
2022-01-26 13:45:17 +00:00
if targetFrom is not None:
returns = {}
for m in ModulesManager.modules:
if isinstance(ModulesManager.modules[m], (Command, RegexCommand, Schedule, StartUp)):
if targetFrom in ModulesManager.modules[m].exclude_from:
continue
available = ModulesManager.modules[m].available_for
if targetFrom in available or '*' in available:
returns.update({m: ModulesManager.modules[m]})
return returns
2021-10-24 10:55:45 +00:00
return ModulesManager.modules
2021-07-08 15:51:58 +00:00
2021-08-30 18:53:39 +00:00
@staticmethod
2021-10-14 15:18:47 +00:00
def return_modules_alias_map() -> Dict[str, str]:
2021-10-12 15:02:36 +00:00
"""
返回每个别名映射到的模块
"""
2021-10-24 10:55:45 +00:00
modules = ModulesManager.return_modules_list_as_dict()
2021-11-09 13:48:41 +00:00
alias_map = {}
2021-10-24 10:55:45 +00:00
for m in modules:
module = modules[m]
2021-11-09 13:48:41 +00:00
if module.alias is not None:
alias_map.update(module.alias)
2021-07-08 15:51:58 +00:00
return alias_map
2021-10-12 15:02:36 +00:00
@staticmethod
2021-11-19 16:33:53 +00:00
def return_module_alias(module_name) -> Dict[str, str]:
2021-10-12 15:02:36 +00:00
"""
2021-10-15 17:36:22 +00:00
返回此模块的别名列表
2021-10-12 15:02:36 +00:00
"""
2021-10-15 17:36:22 +00:00
module = ModulesManager.return_modules_list_as_dict()[module_name]
if module.alias is None:
2021-11-09 13:48:41 +00:00
return {}
return module.alias
2021-10-12 15:02:36 +00:00
2021-09-19 12:52:42 +00:00
@staticmethod
2021-10-14 15:18:47 +00:00
def return_modules_developers_map() -> Dict[str, list]:
2021-09-19 12:52:42 +00:00
d = {}
2021-10-24 10:55:45 +00:00
modules = ModulesManager.return_modules_list_as_dict()
for m in modules:
module = modules[m]
if module.developers is not None:
2021-11-09 13:48:41 +00:00
d.update({m: module.developers})
2021-09-19 12:52:42 +00:00
return d
2021-08-30 18:53:39 +00:00
@staticmethod
2022-07-01 14:14:26 +00:00
def return_specified_type_modules(module_type: [Command, RegexCommand, Schedule, StartUp],
2022-01-26 13:45:17 +00:00
targetFrom: str = None) \
2022-07-31 08:33:20 +00:00
-> Dict[str, Union[Command, RegexCommand, Schedule, StartUp]]:
2021-07-26 14:33:49 +00:00
d = {}
2021-10-24 10:55:45 +00:00
modules = ModulesManager.return_modules_list_as_dict()
for m in modules:
module = modules[m]
2021-11-09 13:48:41 +00:00
if isinstance(module, module_type):
2022-01-26 13:45:17 +00:00
if targetFrom is not None:
if isinstance(module, (Command, RegexCommand, Schedule, StartUp)):
if targetFrom in module.exclude_from:
continue
if targetFrom in module.available_for or '*' in module.available_for:
d.update({m: module})
else:
d.update({module.bind_prefix: module})
2021-07-26 14:33:49 +00:00
return d
2023-01-26 07:31:13 +00:00
@staticmethod
2023-01-28 05:53:11 +00:00
def reload_module(module_name: str):
2023-01-26 07:31:13 +00:00
"""
2023-01-26 13:21:46 +00:00
重载该小可模块以及该模块所在文件的其它模块
"""
py_module = ModulesManager.return_py_module(module_name)
unbind_modules = ModulesManager.search_related_module(module_name)
ModulesManager.remove_modules(unbind_modules)
return ModulesManager.reload_py_module(py_module)
2023-01-28 05:53:11 +00:00
2023-01-26 13:21:46 +00:00
@staticmethod
2023-01-28 05:53:11 +00:00
def reload_py_module(module_name: str):
2023-01-26 13:21:46 +00:00
"""
重载该py模块
2023-01-26 07:31:13 +00:00
"""
try:
2023-01-28 05:44:03 +00:00
Logger.info(f'Reloading {module_name} ...')
2023-01-26 13:21:46 +00:00
module = sys.modules[module_name]
2023-01-26 07:31:13 +00:00
cnt = 0
loadedModList = list(sys.modules.keys())
for mod in loadedModList:
2023-01-26 13:21:46 +00:00
if mod.startswith(f'{module_name}.'):
cnt += ModulesManager.reload_py_module(mod)
2023-01-26 07:31:13 +00:00
importlib.reload(module)
2023-01-26 13:21:46 +00:00
Logger.info(f'Succeeded reloaded {module_name}')
return cnt + 1
2023-01-26 07:31:13 +00:00
except:
tb = traceback.format_exc()
errmsg = f'Failed to reload {module_name}: \n{tb}'
Logger.error(errmsg)
2023-01-28 05:44:03 +00:00
return -999