Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

204 строки
5.8KB

  1. import json
  2. import sys
  3. from flask import Blueprint, request, send_from_directory
  4. from importlib import import_module
  5. from modules import socketio, cbpi
  6. from modules.utils import chown_unroot
  7. from git import Repo
  8. import os
  9. import requests
  10. import yaml
  11. import shutil
  12. blueprint = Blueprint('addon', __name__)
  13. modules = {}
  14. def merge(source, destination):
  15. """
  16. Helper method to merge two dicts
  17. :param source:
  18. :param destination:
  19. :return:
  20. """
  21. for key, value in source.items():
  22. if isinstance(value, dict):
  23. # get node or create one
  24. node = destination.setdefault(key, {})
  25. merge(value, node)
  26. else:
  27. destination[key] = value
  28. return destination
  29. @blueprint.route('/', methods=['GET'])
  30. def getPlugins():
  31. """
  32. Endpoint for all plugins
  33. :return:
  34. """
  35. result = []
  36. for filename in os.listdir("./modules/plugins"):
  37. if filename.endswith(".DS_Store") or filename.endswith(".py") or filename.endswith(".pyc"):
  38. continue
  39. result.append(filename)
  40. return json.dumps(result)
  41. @blueprint.route('/<name>', methods=['GET'])
  42. def getFile(name):
  43. """
  44. Returns plugin code
  45. :param name: plugin name
  46. :return: the plugin code from __init__.py
  47. """
  48. return send_from_directory('./plugins/'+name, "__init__.py")
  49. @blueprint.route('/<name>', methods=['PUT'])
  50. def createPlugin(name):
  51. """
  52. Create a new plugin file
  53. :param name: the plugin name
  54. :return: empty http response 204
  55. """
  56. if not os.path.exists("./modules/plugins/"+name):
  57. os.makedirs("./modules/plugins/"+name)
  58. with open("./modules/plugins/" + name + "/__init__.py", "wb") as fo:
  59. fo.write("")
  60. cbpi.emit_message("PLUGIN %s CREATED" % (name))
  61. return ('', 204)
  62. else:
  63. cbpi.emit_message("Failed to create plugin %s. Name arlready in use" % (name))
  64. return ('', 500)
  65. @blueprint.route('/<name>', methods=['POST'])
  66. def saveFile(name):
  67. """
  68. save plugin code. code is provides via http body
  69. :param name: the plugin name
  70. :return: empty http reponse
  71. """
  72. with open("./modules/plugins/"+name+"/__init__.py", "wb") as fo:
  73. fo.write(request.get_data())
  74. cbpi.emit_message("PLUGIN %s SAVED" % (name))
  75. return ('', 204)
  76. @blueprint.route('/<name>', methods=['DELETE'])
  77. def deletePlugin(name):
  78. """
  79. Delete plugin
  80. :param name: plugin name
  81. :return: HTTP 204 if ok - HTTP 500 if plugin not exists
  82. """
  83. if os.path.isdir("./modules/plugins/"+name) is False:
  84. return ('Dir Not found', 500)
  85. shutil.rmtree("./modules/plugins/"+name)
  86. cbpi.notify("Plugin deleted", "Plugin %s deleted successfully" % name)
  87. return ('', 204)
  88. @blueprint.route('/<name>/reload/', methods=['POST'])
  89. def reload(name):
  90. """
  91. hot reload plugnin
  92. :param name:
  93. :return:
  94. """
  95. try:
  96. if name in cache["modules"]:
  97. reload(cache["modules"][name])
  98. cbpi.emit_message("REALOD OF PLUGIN %s SUCCESSFUL" % (name))
  99. return ('', 204)
  100. else:
  101. cache["modules"][name] = import_module("modules.plugins.%s" % (name))
  102. return ('', 204)
  103. except Exception as e:
  104. cbpi.emit_message("REALOD OF PLUGIN %s FAILED" % (name))
  105. return json.dumps(e.message)
  106. @blueprint.route('/list', methods=['GET'])
  107. def plugins():
  108. """
  109. Read the central plugin yaml to get a list of all official plugins
  110. :return:
  111. """
  112. response = requests.get("https://raw.githubusercontent.com/Manuel83/craftbeerpi-plugins/master/plugins.yaml")
  113. cbpi.cache["plugins"] = merge(yaml.load(response.text), cbpi.cache["plugins"])
  114. for key, value in cbpi.cache["plugins"].iteritems():
  115. value["installed"] = os.path.isdir("./modules/plugins/%s/" % (key))
  116. return json.dumps(cbpi.cache["plugins"])
  117. @blueprint.route('/<name>/download', methods=['POST'])
  118. def download_addon(name):
  119. plugin = cbpi.cache["plugins"].get(name)
  120. plugin["loading"] = True
  121. if plugin is None:
  122. return ('', 404)
  123. try:
  124. module_path= "./modules/plugins/%s/" % (name)
  125. Repo.clone_from(plugin.get("repo_url"), module_path)
  126. chown_unroot(module_path)
  127. cbpi.notify("Download successful", "Plugin %s downloaded successfully" % name)
  128. finally:
  129. plugin["loading"] = False
  130. return ('', 204)
  131. @blueprint.route('/<name>/update', methods=['POST'])
  132. def update_addon(name):
  133. module_path= "./modules/plugins/%s/" % (name)
  134. repo = Repo(module_path)
  135. o = repo.remotes.origin
  136. info = o.pull()
  137. chown_unroot(module_path)
  138. cbpi.notify("Plugin Updated", "Plugin %s updated successfully. Please restart the system" % name)
  139. return ('', 204)
  140. def loadCorePlugins():
  141. for filename in os.listdir("./modules/base_plugins"):
  142. if filename.endswith(".py") or filename.endswith(".pyc"):
  143. continue
  144. try:
  145. modules[filename] = import_module("modules.base_plugins.%s" % (filename))
  146. except Exception as e:
  147. cbpi.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None)
  148. cbpi.app.logger.error(e)
  149. def loadPlugins():
  150. for filename in os.listdir("./modules/plugins"):
  151. if filename.endswith(".py") or filename.endswith(".pyc"):
  152. continue
  153. try:
  154. modules[filename] = import_module("modules.plugins.%s" % (filename))
  155. except Exception as e:
  156. cbpi.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None)
  157. cbpi.app.logger.error(e)
  158. @cbpi.initalizer(order=1)
  159. def initPlugins(app):
  160. print "INITIALIZE CUSTOM PLUGINS"
  161. loadCorePlugins()
  162. loadPlugins()
  163. @cbpi.initalizer(order=2)
  164. def init(cbpi):
  165. print "INITIALIZE ADDON MODULE"
  166. cbpi.app.register_blueprint(blueprint, url_prefix='/api/editor')