diff options
Diffstat (limited to 'backend/browser.py')
| -rw-r--r-- | backend/browser.py | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/backend/browser.py b/backend/browser.py index 83c68d47..8e2209f1 100644 --- a/backend/browser.py +++ b/backend/browser.py @@ -3,19 +3,19 @@ import json # Partial imports from aiohttp import ClientSession, web -from asyncio import get_event_loop +from asyncio import get_event_loop, sleep from concurrent.futures import ProcessPoolExecutor from hashlib import sha256 from io import BytesIO from logging import getLogger -from os import path, rename, listdir +from os import R_OK, W_OK, path, rename, listdir, access, mkdir from shutil import rmtree from subprocess import call from time import time from zipfile import ZipFile # Local modules -from helpers import get_ssl_context, get_user, get_user_group +from helpers import get_ssl_context, get_user, get_user_group, download_remote_binary_to_path from injector import get_tab, inject_to_tab logger = getLogger("Browser") @@ -28,9 +28,10 @@ class PluginInstallContext: self.hash = hash class PluginBrowser: - def __init__(self, plugin_path, plugins) -> None: + def __init__(self, plugin_path, plugins, loader) -> None: self.plugin_path = plugin_path self.plugins = plugins + self.loader = loader self.install_requests = {} def _unzip_to_plugin_dir(self, zip, name, hash): @@ -39,12 +40,55 @@ class PluginBrowser: return False zip_file = ZipFile(zip) zip_file.extractall(self.plugin_path) - code_chown = call(["chown", "-R", get_user()+":"+get_user_group(), self.plugin_path]) - code_chmod = call(["chmod", "-R", "555", self.plugin_path]) + plugin_dir = self.find_plugin_folder(name) + code_chown = call(["chown", "-R", get_user()+":"+get_user_group(), plugin_dir]) + code_chmod = call(["chmod", "-R", "555", plugin_dir]) if code_chown != 0 or code_chmod != 0: logger.error(f"chown/chmod exited with a non-zero exit code (chown: {code_chown}, chmod: {code_chmod})") return False return True + + async def _download_remote_binaries_for_plugin_with_name(self, pluginBasePath): + rv = False + try: + packageJsonPath = path.join(pluginBasePath, 'package.json') + pluginBinPath = path.join(pluginBasePath, 'bin') + + if access(packageJsonPath, R_OK): + with open(packageJsonPath, 'r') as f: + packageJson = json.load(f) + if len(packageJson["remote_binary"]) > 0: + # create bin directory if needed. + rc=call(["chmod", "-R", "777", pluginBasePath]) + if access(pluginBasePath, W_OK): + + if not path.exists(pluginBinPath): + mkdir(pluginBinPath) + + if not access(pluginBinPath, W_OK): + rc=call(["chmod", "-R", "777", pluginBinPath]) + + rv = True + for remoteBinary in packageJson["remote_binary"]: + # Required Fields. If any Remote Binary is missing these fail the install. + binName = remoteBinary["name"] + binURL = remoteBinary["url"] + binHash = remoteBinary["sha256hash"] + if not await download_remote_binary_to_path(binURL, binHash, path.join(pluginBinPath, binName)): + rv = False + raise Exception(f"Error Downloading Remote Binary {binName}@{binURL} with hash {binHash} to {path.join(pluginBinPath, binName)}") + + code_chown = call(["chown", "-R", get_user()+":"+get_user_group(), self.plugin_path]) + rc=call(["chmod", "-R", "555", pluginBasePath]) + else: + rv = True + logger.debug(f"No Remote Binaries to Download") + + except Exception as e: + rv = False + logger.debug(str(e)) + + return rv def find_plugin_folder(self, name): for folder in listdir(self.plugin_path): @@ -58,6 +102,8 @@ class PluginBrowser: logger.debug(f"skipping {folder}") async def uninstall_plugin(self, name): + if self.loader.watcher: + self.loader.watcher.disabled = True tab = await get_tab("SP") try: logger.info("uninstalling " + name) @@ -74,8 +120,12 @@ class PluginBrowser: except Exception as e: logger.error(f"Plugin {name} in {self.find_plugin_folder(name)} was not uninstalled") logger.error(f"Error at %s", exc_info=e) + if self.loader.watcher: + self.loader.watcher.disabled = False async def _install(self, artifact, name, version, hash): + if self.loader.watcher: + self.loader.watcher.disabled = True try: await self.uninstall_plugin(name) except: @@ -92,10 +142,22 @@ class PluginBrowser: logger.debug("Unzipping...") ret = self._unzip_to_plugin_dir(res_zip, name, hash) if ret: - logger.info(f"Installed {name} (Version: {version})") - await inject_to_tab("SP", "window.syncDeckyPlugins()") + plugin_dir = self.find_plugin_folder(name) + ret = await self._download_remote_binaries_for_plugin_with_name(plugin_dir) + if ret: + logger.info(f"Installed {name} (Version: {version})") + if name in self.loader.plugins: + self.loader.plugins[name].stop() + self.loader.plugins.pop(name, None) + await sleep(1) + self.loader.import_plugin(path.join(plugin_dir, "main.py"), plugin_dir) + # await inject_to_tab("SP", "window.syncDeckyPlugins()") + else: + logger.fatal(f"Failed Downloading Remote Binaries") else: self.log.fatal(f"SHA-256 Mismatch!!!! {name} (Version: {version})") + if self.loader.watcher: + self.loader.watcher.disabled = False else: logger.fatal(f"Could not fetch from URL. {await res.text()}") |
