summaryrefslogtreecommitdiff
path: root/backend/browser.py
diff options
context:
space:
mode:
Diffstat (limited to 'backend/browser.py')
-rw-r--r--backend/browser.py114
1 files changed, 81 insertions, 33 deletions
diff --git a/backend/browser.py b/backend/browser.py
index dbdf2d5f..1c239399 100644
--- a/backend/browser.py
+++ b/backend/browser.py
@@ -1,27 +1,33 @@
# Full imports
import json
+
# import pprint
# from pprint import pformat
# Partial imports
-from aiohttp import ClientSession, web
-from asyncio import get_event_loop, sleep
-from concurrent.futures import ProcessPoolExecutor
+from aiohttp import ClientSession
+from asyncio import sleep
from hashlib import sha256
from io import BytesIO
from logging import getLogger
-from os import R_OK, W_OK, path, rename, listdir, access, mkdir
+from os import R_OK, W_OK, path, 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, download_remote_binary_to_path
+from helpers import (
+ get_ssl_context,
+ get_user,
+ get_user_group,
+ download_remote_binary_to_path,
+)
from injector import get_gamepadui_tab
logger = getLogger("Browser")
+
class PluginInstallContext:
def __init__(self, artifact, name, version, hash) -> None:
self.artifact = artifact
@@ -29,6 +35,7 @@ class PluginInstallContext:
self.version = version
self.hash = hash
+
class PluginBrowser:
def __init__(self, plugin_path, plugins, loader) -> None:
self.plugin_path = plugin_path
@@ -43,32 +50,40 @@ class PluginBrowser:
zip_file = ZipFile(zip)
zip_file.extractall(self.plugin_path)
plugin_dir = self.find_plugin_folder(name)
- code_chown = call(["chown", "-R", get_user()+":"+get_user_group(), plugin_dir])
+ 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})")
+ logger.error(
+ f"chown/chmod exited with a non-zero exit code (chown: {code_chown},"
+ f" 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')
+ packageJsonPath = path.join(pluginBasePath, "package.json")
+ pluginBinPath = path.join(pluginBasePath, "bin")
if access(packageJsonPath, R_OK):
with open(packageJsonPath, "r", encoding="utf-8") as f:
packageJson = json.load(f)
- if "remote_binary" in packageJson and len(packageJson["remote_binary"]) > 0:
+ if (
+ "remote_binary" in packageJson
+ and len(packageJson["remote_binary"]) > 0
+ ):
# create bin directory if needed.
- rc=call(["chmod", "-R", "777", pluginBasePath])
+ 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])
+ call(["chmod", "-R", "777", pluginBinPath])
rv = True
for remoteBinary in packageJson["remote_binary"]:
@@ -76,16 +91,29 @@ class PluginBrowser:
binName = remoteBinary["name"]
binURL = remoteBinary["url"]
binHash = remoteBinary["sha256hash"]
- if not await download_remote_binary_to_path(binURL, binHash, path.join(pluginBinPath, binName)):
+ 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])
+ raise Exception(
+ "Error Downloading Remote Binary"
+ f" {binName}@{binURL} with hash {binHash} to"
+ f" {path.join(pluginBinPath, binName)}"
+ )
+
+ call(
+ [
+ "chown",
+ "-R",
+ get_user() + ":" + get_user_group(),
+ self.plugin_path,
+ ]
+ )
+ call(["chmod", "-R", "555", pluginBasePath])
else:
rv = True
- logger.debug(f"No Remote Binaries to Download")
-
+ logger.debug("No Remote Binaries to Download")
+
except Exception as e:
rv = False
logger.debug(str(e))
@@ -95,10 +123,14 @@ class PluginBrowser:
def find_plugin_folder(self, name):
for folder in listdir(self.plugin_path):
try:
- with open(path.join(self.plugin_path, folder, 'plugin.json'), "r", encoding="utf-8") as f:
+ with open(
+ path.join(self.plugin_path, folder, "plugin.json"),
+ "r",
+ encoding="utf-8",
+ ) as f:
plugin = json.load(f)
- if plugin['name'] == name:
+ if plugin["name"] == name:
return str(path.join(self.plugin_path, folder))
except:
logger.debug(f"skipping {folder}")
@@ -127,8 +159,10 @@ class PluginBrowser:
except FileNotFoundError:
logger.warning(f"Plugin {name} not installed, skipping uninstallation")
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)
+ logger.error(
+ f"Plugin {name} in {self.find_plugin_folder(name)} was not uninstalled"
+ )
+ logger.error("Error at %s", exc_info=e)
if self.loader.watcher:
self.loader.watcher.disabled = False
@@ -141,7 +175,10 @@ class PluginBrowser:
if pluginFolderPath:
isInstalled = True
except:
- logger.error(f"Failed to determine if {name} is already installed, continuing anyway.")
+ logger.error(
+ f"Failed to determine if {name} is already installed, continuing"
+ " anyway."
+ )
logger.info(f"Installing {name} (Version: {version})")
async with ClientSession() as client:
logger.debug(f"Fetching {artifact}")
@@ -161,16 +198,20 @@ class PluginBrowser:
ret = self._unzip_to_plugin_dir(res_zip, name, hash)
if ret:
plugin_dir = self.find_plugin_folder(name)
- ret = await self._download_remote_binaries_for_plugin_with_name(plugin_dir)
+ 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)
+ self.loader.import_plugin(
+ path.join(plugin_dir, "main.py"), plugin_dir
+ )
else:
- logger.fatal(f"Failed Downloading Remote Binaries")
+ logger.fatal("Failed Downloading Remote Binaries")
else:
self.log.fatal(f"SHA-256 Mismatch!!!! {name} (Version: {version})")
if self.loader.watcher:
@@ -180,14 +221,21 @@ class PluginBrowser:
async def request_plugin_install(self, artifact, name, version, hash):
request_id = str(time())
- self.install_requests[request_id] = PluginInstallContext(artifact, name, version, hash)
+ self.install_requests[request_id] = PluginInstallContext(
+ artifact, name, version, hash
+ )
tab = await get_gamepadui_tab()
await tab.open_websocket()
- await tab.evaluate_js(f"DeckyPluginLoader.addPluginInstallPrompt('{name}', '{version}', '{request_id}', '{hash}')")
+ await tab.evaluate_js(
+ f"DeckyPluginLoader.addPluginInstallPrompt('{name}', '{version}',"
+ f" '{request_id}', '{hash}')"
+ )
async def confirm_plugin_install(self, request_id):
request = self.install_requests.pop(request_id)
- await self._install(request.artifact, request.name, request.version, request.hash)
+ await self._install(
+ request.artifact, request.name, request.version, request.hash
+ )
def cancel_plugin_install(self, request_id):
self.install_requests.pop(request_id)