您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

131 行
4.8KB

  1. # encoding:utf-8
  2. import importlib
  3. import json
  4. import os
  5. from common.singleton import singleton
  6. from .event import *
  7. from .plugin import *
  8. from common.log import logger
  9. @singleton
  10. class PluginManager:
  11. def __init__(self):
  12. self.plugins = {}
  13. self.listening_plugins = {}
  14. self.instances = {}
  15. self.pconf = {}
  16. def register(self, name: str, desc: str, version: str, author: str):
  17. def wrapper(plugincls):
  18. self.plugins[name] = plugincls
  19. plugincls.name = name
  20. plugincls.desc = desc
  21. plugincls.version = version
  22. plugincls.author = author
  23. plugincls.enabled = True
  24. logger.info("Plugin %s_v%s registered" % (name, version))
  25. return plugincls
  26. return wrapper
  27. def save_config(self):
  28. with open("plugins/plugins.json", "w", encoding="utf-8") as f:
  29. json.dump(self.pconf, f, indent=4, ensure_ascii=False)
  30. def load_config(self):
  31. logger.info("Loading plugins config...")
  32. modified = False
  33. if os.path.exists("plugins/plugins.json"):
  34. with open("plugins/plugins.json", "r", encoding="utf-8") as f:
  35. pconf = json.load(f)
  36. else:
  37. modified = True
  38. pconf = {"plugins": []}
  39. self.pconf = pconf
  40. if modified:
  41. self.save_config()
  42. return pconf
  43. def scan_plugins(self):
  44. logger.info("Scaning plugins ...")
  45. plugins_dir = "plugins"
  46. for plugin_name in os.listdir(plugins_dir):
  47. plugin_path = os.path.join(plugins_dir, plugin_name)
  48. if os.path.isdir(plugin_path):
  49. # 判断插件是否包含同名.py文件
  50. main_module_path = os.path.join(plugin_path, plugin_name+".py")
  51. if os.path.isfile(main_module_path):
  52. # 导入插件
  53. import_path = "{}.{}.{}".format(plugins_dir, plugin_name, plugin_name)
  54. main_module = importlib.import_module(import_path)
  55. pconf = self.pconf
  56. new_plugins = []
  57. modified = False
  58. for name, plugincls in self.plugins.items():
  59. if name not in [plugin["name"] for plugin in pconf["plugins"]]:
  60. new_plugins.append(plugincls)
  61. modified = True
  62. logger.info("Plugin %s not found in pconfig, adding to pconfig..." % name)
  63. pconf["plugins"].append({"name": name, "enabled": True})
  64. if modified:
  65. self.save_config()
  66. return new_plugins
  67. def activate_plugins(self):
  68. for name, plugincls in self.plugins.items():
  69. if plugincls.enabled:
  70. if name not in self.instances:
  71. instance = plugincls()
  72. self.instances[name] = instance
  73. for event in instance.handlers:
  74. if event not in self.listening_plugins:
  75. self.listening_plugins[event] = []
  76. self.listening_plugins[event].append(name)
  77. def load_plugins(self):
  78. self.load_config()
  79. self.scan_plugins()
  80. pconf = self.pconf
  81. logger.debug("plugins.json config={}".format(pconf))
  82. for plugin in pconf["plugins"]:
  83. name = plugin["name"]
  84. enabled = plugin["enabled"]
  85. self.plugins[name].enabled = enabled
  86. self.activate_plugins()
  87. def emit_event(self, e_context: EventContext, *args, **kwargs):
  88. if e_context.event in self.listening_plugins:
  89. for name in self.listening_plugins[e_context.event]:
  90. if self.plugins[name].enabled and e_context.action == EventAction.CONTINUE:
  91. logger.debug("Plugin %s triggered by event %s" % (name,e_context.event))
  92. instance = self.instances[name]
  93. instance.handlers[e_context.event](e_context, *args, **kwargs)
  94. return e_context
  95. def enable_plugin(self,name):
  96. if name not in self.plugins:
  97. return False
  98. if not self.plugins[name].enabled :
  99. self.plugins[name].enabled = True
  100. idx = next(i for i in range(len(self.pconf['plugins'])) if self.pconf["plugins"][i]['name'] == name)
  101. self.pconf["plugins"][idx]["enabled"] = True
  102. self.save_config()
  103. self.activate_plugins()
  104. return True
  105. return True
  106. def disable_plugin(self,name):
  107. if name not in self.plugins:
  108. return False
  109. if self.plugins[name].enabled :
  110. self.plugins[name].enabled = False
  111. idx = next(i for i in range(len(self.pconf['plugins'])) if self.pconf["plugins"][i]['name'] == name)
  112. self.pconf["plugins"][idx]["enabled"] = False
  113. self.save_config()
  114. return True
  115. return True
  116. def list_plugins(self):
  117. return self.plugins