From cd5a09938fa2d5eae8d033dc44e9fd47100d0c1e Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 20 Jul 2017 22:04:44 +0200 Subject: [PATCH] Add support for logo --- API.md | 5 ++++- hassio/addons/addon.py | 18 ++++++++++++++---- hassio/api/__init__.py | 1 + hassio/api/addons.py | 13 ++++++++++++- hassio/api/util.py | 26 +++++++++++++++----------- hassio/const.py | 4 ++++ hassio/dock/addon.py | 2 +- 7 files changed, 51 insertions(+), 18 deletions(-) diff --git a/API.md b/API.md index 8d15758c8..8a16774a8 100644 --- a/API.md +++ b/API.md @@ -332,10 +332,13 @@ Get all available addons "build": "bool", "options": "{}", "network": "{}|null", - "host_network": "bool" + "host_network": "bool", + "logo": "bool" } ``` +- GET `/addons/{addon}/logo` + - POST `/addons/{addon}/options` ```json { diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index 139b28e2a..07b3fd9ee 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -19,7 +19,7 @@ from ..const import ( ATTR_URL, ATTR_ARCH, ATTR_LOCATON, ATTR_DEVICES, ATTR_ENVIRONMENT, ATTR_HOST_NETWORK, ATTR_TMPFS, ATTR_PRIVILEGED, ATTR_STARTUP, STATE_STARTED, STATE_STOPPED, STATE_NONE, ATTR_USER, ATTR_SYSTEM, - ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK) + ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_LOGO) from .util import check_installed from ..dock.addon import DockerAddon from ..tools import write_json_file, read_json_file @@ -228,6 +228,11 @@ class Addon(object): """Return url of addon.""" return self._mesh.get(ATTR_URL) + @property + def with_logo(self): + """Return True if a logo exists.""" + return self.path_logo.exists() + @property def supported_arch(self): """Return list of supported arch.""" @@ -273,15 +278,20 @@ class Addon(object): return PurePath(self.config.path_extern_addons_data, self._id) @property - def path_addon_options(self): + def path_options(self): """Return path to addons options.""" return Path(self.path_data, "options.json") @property - def path_addon_location(self): + def path_location(self): """Return path to this addon.""" return Path(self._mesh[ATTR_LOCATON]) + @property + def path_logo(self): + """Return path to addon logo.""" + return Path(self.path_location, 'logo.png') + def write_options(self): """Return True if addon options is written to data.""" schema = self.schema @@ -289,7 +299,7 @@ class Addon(object): try: schema(options) - return write_json_file(self.path_addon_options, options) + return write_json_file(self.path_options, options) except vol.Invalid as ex: _LOGGER.error("Addon %s have wrong options -> %s", self._id, humanize_error(options, ex)) diff --git a/hassio/api/__init__.py b/hassio/api/__init__.py index 1fbcbc40a..f09dd0b43 100644 --- a/hassio/api/__init__.py +++ b/hassio/api/__init__.py @@ -94,6 +94,7 @@ class RestAPI(object): self.webapp.router.add_post( '/addons/{addon}/options', api_addons.options) self.webapp.router.add_get('/addons/{addon}/logs', api_addons.logs) + self.webapp.router.add_get('/addons/{addon}/logo', api_addons.logo) def register_security(self): """Register security function.""" diff --git a/hassio/api/addons.py b/hassio/api/addons.py index 2e805bf52..481eb8c78 100644 --- a/hassio/api/addons.py +++ b/hassio/api/addons.py @@ -11,7 +11,7 @@ from ..const import ( ATTR_URL, ATTR_DESCRIPTON, ATTR_DETACHED, ATTR_NAME, ATTR_REPOSITORY, ATTR_BUILD, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_HOST_NETWORK, ATTR_SLUG, ATTR_SOURCE, ATTR_REPOSITORIES, ATTR_ADDONS, ATTR_ARCH, ATTR_MAINTAINER, - ATTR_INSTALLED, BOOT_AUTO, BOOT_MANUAL) + ATTR_INSTALLED, ATTR_LOGO, BOOT_AUTO, BOOT_MANUAL, CONTENT_TYPE_PNG) from ..validate import DOCKER_PORTS _LOGGER = logging.getLogger(__name__) @@ -64,6 +64,7 @@ class APIAddons(object): ATTR_REPOSITORY: addon.repository, ATTR_BUILD: addon.need_build, ATTR_URL: addon.url, + ATTR_LOGO: addon.with_logo, }) data_repositories = [] @@ -187,3 +188,13 @@ class APIAddons(object): """Return logs from addon.""" addon = self._extract_addon(request) return addon.logs() + + @api_process_raw(CONTENT_TYPE_PNG) + def png(self, request): + """Return logo from addon.""" + addon = self._extract_addon(request) + if addon.with_logo: + raise RuntimeError("No image found!") + + with addon.path_logo.open('rb') as png: + return png.read() diff --git a/hassio/api/util.py b/hassio/api/util.py index c1e52e249..3f837d2a5 100644 --- a/hassio/api/util.py +++ b/hassio/api/util.py @@ -9,7 +9,8 @@ import voluptuous as vol from voluptuous.humanize import humanize_error from ..const import ( - JSON_RESULT, JSON_DATA, JSON_MESSAGE, RESULT_OK, RESULT_ERROR) + JSON_RESULT, JSON_DATA, JSON_MESSAGE, RESULT_OK, RESULT_ERROR, + CONTENT_TYPE_BINARY) _LOGGER = logging.getLogger(__name__) @@ -65,18 +66,21 @@ def api_process_hostcontrol(method): return wrap_hostcontrol -def api_process_raw(method): - """Wrap function with raw output to rest api.""" - async def wrap_api(api, *args, **kwargs): - """Return api information.""" - try: - message = await method(api, *args, **kwargs) - except RuntimeError as err: - message = str(err).encode() +def api_process_raw(content=CONTENT_TYPE_BINARY): + def api_raw(method): + """Wrap function with raw output to rest api.""" + async def wrap_api(api, *args, **kwargs): + """Return api information.""" + try: + message = await method(api, *args, **kwargs) + except RuntimeError as err: + message = str(err).encode() + content = CONTENT_TYPE_BINARY - return web.Response(body=message) + return web.Response(body=message, content_type=content) - return wrap_api + return wrap_api + return api_raw def api_return_error(message=None): diff --git a/hassio/const.py b/hassio/const.py index 3088d31fb..20b4e4953 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -44,6 +44,9 @@ JSON_MESSAGE = 'message' RESULT_ERROR = 'error' RESULT_OK = 'ok' +CONTENT_TYPE_BINARY = 'application/octet-stream' +CONTENT_TYPE_PNG = 'image/png' + ATTR_DATE = 'date' ATTR_ARCH = 'arch' ATTR_HOSTNAME = 'hostname' @@ -69,6 +72,7 @@ ATTR_DETACHED = 'detached' ATTR_STATE = 'state' ATTR_SCHEMA = 'schema' ATTR_IMAGE = 'image' +ATTR_LOGO = 'logo' ATTR_ADDONS_REPOSITORIES = 'addons_repositories' ATTR_REPOSITORY = 'repository' ATTR_REPOSITORIES = 'repositories' diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 561e60dca..8e4737b0e 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -144,7 +144,7 @@ class DockerAddon(DockerBase): try: # prepare temporary addon build folder try: - source = self.addon.path_addon_location + source = self.addon.path_location shutil.copytree(str(source), str(build_dir)) except shutil.Error as err: _LOGGER.error("Can't copy %s to temporary build folder -> %s",