|
- import json
-
- import sys
- from flask import Blueprint, request, send_from_directory
- from importlib import import_module
- from modules import socketio, cbpi
-
-
- from git import Repo
- import os
- import requests
- import yaml
- import shutil
-
- blueprint = Blueprint('addon', __name__)
-
- user_yaml = None
-
- modules = {}
-
- def merge(source, destination):
- """
- Helper method to merge two dicts
- :param source:
- :param destination:
- :return:
- """
- for key, value in source.items():
- if isinstance(value, dict):
- # get node or create one
- node = destination.setdefault(key, {})
- merge(value, node)
- else:
- destination[key] = value
-
- return destination
-
- @blueprint.route('/', methods=['GET'])
- def getPlugins():
- """
- Endpoint for all plugins
- :return:
- """
- result = []
- for filename in os.listdir("./modules/plugins"):
- if filename.endswith(".DS_Store") or filename.endswith(".py") or filename.endswith(".pyc"):
- continue
- result.append(filename)
-
- return json.dumps(result)
-
- @blueprint.route('/<name>', methods=['GET'])
- def getFile(name):
- """
- Returns plugin code
- :param name: plugin name
- :return: the plugin code from __init__.py
- """
- return send_from_directory('./plugins/'+name, "__init__.py")
-
- @blueprint.route('/<name>', methods=['PUT'])
- def createPlugin(name):
-
- """
- Create a new plugin file
- :param name: the plugin name
- :return: empty http response 204
- """
- if not os.path.exists("./modules/plugins/"+name):
- os.makedirs("./modules/plugins/"+name)
- with open("./modules/plugins/" + name + "/__init__.py", "wb") as fo:
- fo.write("")
- cbpi.emit_message("PLUGIN %s CREATED" % (name))
- return ('', 204)
- else:
- cbpi.emit_message("Failed to create plugin %s. Name arlready in use" % (name))
- return ('', 500)
-
-
-
-
- @blueprint.route('/<name>', methods=['POST'])
- def saveFile(name):
-
- """
- save plugin code. code is provides via http body
- :param name: the plugin name
- :return: empty http reponse
- """
- with open("./modules/plugins/"+name+"/__init__.py", "wb") as fo:
- fo.write(request.get_data())
- cbpi.emit_message("PLUGIN %s SAVED" % (name))
-
- return ('', 204)
-
- @blueprint.route('/<name>', methods=['DELETE'])
- def deletePlugin(name):
-
- """
- Delete plugin
- :param name: plugin name
- :return: HTTP 204 if ok - HTTP 500 if plugin not exists
- """
- if os.path.isdir("./modules/plugins/"+name) is False:
- return ('Dir Not found', 500)
- shutil.rmtree("./modules/plugins/"+name)
- cbpi.notify("Plugin deleted", "Plugin %s deleted successfully" % name)
- return ('', 204)
-
- @blueprint.route('/<name>/reload/', methods=['POST'])
- def reload(name):
- """
- hot reload plugnin
- :param name:
- :return:
- """
- try:
- if name in cache["modules"]:
- reload(cache["modules"][name])
- cbpi.emit_message("REALOD OF PLUGIN %s SUCCESSFUL" % (name))
- return ('', 204)
- else:
- cache["modules"][name] = import_module("modules.plugins.%s" % (name))
- return ('', 204)
- except Exception as e:
- cbpi.emit_message("REALOD OF PLUGIN %s FAILED" % (name))
- return json.dumps(e.message)
-
-
- @blueprint.route('/list', methods=['GET'])
- def plugins():
- """
- Read the central plugin yaml to get a list of all official plugins
- :return:
- """
- response = requests.get("https://raw.githubusercontent.com/Manuel83/craftbeerpi-plugins/master/plugins.yaml")
- cbpi.cache["plugins"] = merge(yaml.load(response.text), cbpi.cache["plugins"])
- for key, value in cbpi.cache["plugins"].iteritems():
- value["installed"] = os.path.isdir("./modules/plugins/%s/" % (key))
-
- user_yaml=cbpi.get_config_parameter("user_yaml", None)
- if user_yaml is None:
- pass
- else:
- response = requests.get(user_yaml)
- cbpi.cache["plugins"] = merge(yaml.load(response.text), cbpi.cache["plugins"])
- for key, value in cbpi.cache["plugins"].iteritems():
- value["installed"] = os.path.isdir("./modules/plugins/%s/" % (key))
-
- return json.dumps(cbpi.cache["plugins"])
-
-
- @blueprint.route('/<name>/download', methods=['POST'])
- def download_addon(name):
-
- plugin = cbpi.cache["plugins"].get(name)
- plugin["loading"] = True
- if plugin is None:
- return ('', 404)
- try:
- Repo.clone_from(plugin.get("repo_url"), "./modules/plugins/%s/" % (name))
- cbpi.notify("Download successful", "Plugin %s downloaded successfully" % name)
- finally:
- plugin["loading"] = False
-
- return ('', 204)
-
- @blueprint.route('/<name>/update', methods=['POST'])
- def update_addon(name):
- repo = Repo("./modules/plugins/%s/" % (name))
- o = repo.remotes.origin
- info = o.pull()
- cbpi.notify("Plugin Updated", "Plugin %s updated successfully. Please restart the system" % name)
- return ('', 204)
-
-
- def loadCorePlugins():
- for filename in os.listdir("./modules/base_plugins"):
- if filename.endswith(".py") or filename.endswith(".pyc"):
- continue
- try:
- modules[filename] = import_module("modules.base_plugins.%s" % (filename))
- except Exception as e:
-
-
- cbpi.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None)
- cbpi.app.logger.error(e)
-
- def loadPlugins():
- for filename in os.listdir("./modules/plugins"):
- if filename.endswith(".py") or filename.endswith(".pyc"):
- continue
- try:
- modules[filename] = import_module("modules.plugins.%s" % (filename))
- except Exception as e:
- cbpi.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None)
- cbpi.app.logger.error(e)
-
- @cbpi.initalizer(order=1)
- def initPlugins(app):
-
- loadCorePlugins()
- loadPlugins()
-
- @cbpi.initalizer(order=2)
- def init(cbpi):
-
- global user_yaml
- user_yaml = cbpi.get_config_parameter("user_yaml", None)
- if user_yaml is None:
- try:
- cbpi.add_config_parameter("user_yaml", "", "text", "User yaml http address")
- except:
- pass
-
- cbpi.app.register_blueprint(blueprint, url_prefix='/api/editor')
|