diff options
| author | botato <63275405+botatooo@users.noreply.github.com> | 2022-08-27 00:01:23 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-26 21:01:23 -0700 |
| commit | b7d7ca04e12690b5e65259c8806e5e895cdc16aa (patch) | |
| tree | 4cca1b72b69622e536dbb1ba13656d39a9420685 | |
| parent | d4d1c2bbabfcec3c62767e614c9d67f516938af2 (diff) | |
| download | decky-loader-2.0.5-pre18.tar.gz decky-loader-2.0.5-pre18.zip | |
Refractor plugin backend (#111)v2.0.5-pre18
* refractor uninstall plugin backend
* refractor plugin installation method
* Change formatting in browser.py
* Manually format main.py
* Manually format utilities.py
* remove inconsistency
* remove unnecessary linebreaks
* lol what
* last minute pythoning
* Fix async missing
* lint
* more refractor
* await forgotten
* fix: menu not disappearing after first click
* lint
* bug: fix double click on uninstall
* depricate request installs
* basic patch notes viewer, lazy-load settings and store, build frontend as esmodule, add lazy-loaded react-markdown, backend changes to accomodate ESModule frontend
* refractor uninstall plugin backend
* Change formatting in browser.py
* Manually format main.py
* Manually format utilities.py
* remove unnecessary linebreaks
* lol what
* last minute pythoning
* Fix async missing
* rebase onto main
* fix error, fix React crash if patch notes are opened before remote version info is loaded
Co-authored-by: TrainDoctor <traindoctor@protonmail.com>
Co-authored-by: AAGaming <aa@mail.catvibers.me>
| -rw-r--r-- | backend/browser.py | 39 | ||||
| -rw-r--r-- | backend/main.py | 22 | ||||
| -rw-r--r-- | backend/utilities.py | 22 | ||||
| -rw-r--r-- | frontend/src/components/settings/pages/general/Updater.tsx | 64 | ||||
| -rw-r--r-- | frontend/src/plugin-loader.tsx | 11 | ||||
| -rw-r--r-- | frontend/src/store.tsx | 47 |
6 files changed, 86 insertions, 119 deletions
diff --git a/backend/browser.py b/backend/browser.py index 1261c057..c5b4f474 100644 --- a/backend/browser.py +++ b/backend/browser.py @@ -28,16 +28,11 @@ class PluginInstallContext: self.hash = hash class PluginBrowser: - def __init__(self, plugin_path, server_instance, plugins) -> None: + def __init__(self, plugin_path, plugins) -> None: self.plugin_path = plugin_path self.plugins = plugins self.install_requests = {} - server_instance.add_routes([ - web.post("/browser/install_plugin", self.install_plugin), - web.post("/browser/uninstall_plugin", self.uninstall_plugin) - ]) - def _unzip_to_plugin_dir(self, zip, name, hash): zip_hash = sha256(zip.getbuffer()).hexdigest() if hash and (zip_hash != hash): @@ -64,25 +59,19 @@ class PluginBrowser: async def uninstall_plugin(self, name): tab = await get_tab("SP") - try: - if type(name) != str: - data = await name.post() - name = data.get("name", "undefined") logger.info("uninstalling " + name) logger.info(" at dir " + self.find_plugin_folder(name)) await tab.evaluate_js(f"DeckyPluginLoader.unloadPlugin('{name}')") if self.plugins[name]: self.plugins[name].stop() - self.plugins.pop(name, None) + self.plugins.remove(name) rmtree(self.find_plugin_folder(name)) except FileNotFoundError: logger.warning(f"Plugin {name} not installed, skipping uninstallation") - return web.Response(text="Requested plugin uninstall") - async def _install(self, artifact, name, version, hash): - try: + try: await self.uninstall_plugin(name) except: logger.error(f"Plugin {name} not installed, skipping uninstallation") @@ -95,29 +84,23 @@ class PluginBrowser: data = await res.read() logger.debug(f"Read {len(data)} bytes") res_zip = BytesIO(data) - with ProcessPoolExecutor() as executor: - 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()") - else: - logger.fatal(f"SHA-256 Mismatch!!!! {name} (Version: {version})") + 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()") + else: + self.log.fatal(f"SHA-256 Mismatch!!!! {name} (Version: {version})") else: logger.fatal(f"Could not fetch from URL. {await res.text()}") - async def install_plugin(self, request): - data = await request.post() - get_event_loop().create_task(self.request_plugin_install(data.get("artifact", ""), data.get("name", "No name"), data.get("version", "dev"), data.get("hash", False))) - return web.Response(text="Requested plugin install") - async def request_plugin_install(self, artifact, name, version, hash): request_id = str(time()) self.install_requests[request_id] = PluginInstallContext(artifact, name, version, hash) tab = await get_tab("SP") await tab.open_websocket() await tab.evaluate_js(f"DeckyPluginLoader.addPluginInstallPrompt('{name}', '{version}', '{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) diff --git a/backend/main.py b/backend/main.py index dfbf1829..1f365fe5 100644 --- a/backend/main.py +++ b/backend/main.py @@ -36,10 +36,15 @@ CONFIG = { "server_host": getenv("SERVER_HOST", "127.0.0.1"), "server_port": int(getenv("SERVER_PORT", "1337")), "live_reload": getenv("LIVE_RELOAD", "1") == "1", - "log_level": {"CRITICAL": 50, "ERROR": 40, "WARNING":30, "INFO": 20, "DEBUG": 10}[getenv("LOG_LEVEL", "INFO")] + "log_level": {"CRITICAL": 50, "ERROR": 40, "WARNING": 30, "INFO": 20, "DEBUG": 10}[ + getenv("LOG_LEVEL", "INFO") + ], } -basicConfig(level=CONFIG["log_level"], format="[%(module)s][%(levelname)s]: %(message)s") +basicConfig( + level=CONFIG["log_level"], + format="[%(module)s][%(levelname)s]: %(message)s" +) logger = getLogger("Main") @@ -55,11 +60,14 @@ class PluginManager: self.web_app = Application() self.web_app.middlewares.append(csrf_middleware) self.cors = aiohttp_cors.setup(self.web_app, defaults={ - "https://steamloopback.host": aiohttp_cors.ResourceOptions(expose_headers="*", - allow_headers="*", allow_credentials=True) + "https://steamloopback.host": aiohttp_cors.ResourceOptions( + expose_headers="*", + allow_headers="*", + allow_credentials=True + ) }) self.plugin_loader = Loader(self.web_app, CONFIG["plugin_path"], self.loop, CONFIG["live_reload"]) - self.plugin_browser = PluginBrowser(CONFIG["plugin_path"], self.web_app, self.plugin_loader.plugins) + self.plugin_browser = PluginBrowser(CONFIG["plugin_path"], self.plugin_loader.plugins) self.settings = SettingsManager("loader", path.join(HOMEBREW_PATH, "settings")) self.utilities = Utilities(self) self.updater = Updater(self) @@ -75,7 +83,7 @@ class PluginManager: self.web_app.add_routes([get("/auth/token", self.get_auth_token)]) for route in list(self.web_app.router.routes()): - self.cors.add(route) + self.cors.add(route) self.web_app.add_routes([static("/static", path.join(path.dirname(__file__), 'static'))]) self.web_app.add_routes([static("/legacy", path.join(path.dirname(__file__), 'legacy'))]) @@ -99,7 +107,7 @@ class PluginManager: async def load_plugins(self): await self.wait_for_server() self.plugin_loader.import_plugins() - #await inject_to_tab("SP", "window.syncDeckyPlugins();") + # await inject_to_tab("SP", "window.syncDeckyPlugins();") async def loader_reinjector(self): await sleep(2) diff --git a/backend/utilities.py b/backend/utilities.py index e06e770d..b3431cb6 100644 --- a/backend/utilities.py +++ b/backend/utilities.py @@ -7,14 +7,17 @@ from injector import inject_to_tab import helpers import subprocess + class Utilities: def __init__(self, context) -> None: self.context = context self.util_methods = { "ping": self.ping, "http_request": self.http_request, + "install_plugin": self.install_plugin, "cancel_plugin_install": self.cancel_plugin_install, "confirm_plugin_install": self.confirm_plugin_install, + "uninstall_plugin": self.uninstall_plugin, "execute_in_tab": self.execute_in_tab, "inject_css_into_tab": self.inject_css_into_tab, "remove_css_from_tab": self.remove_css_from_tab, @@ -45,12 +48,23 @@ class Utilities: res["success"] = False return web.json_response(res) + async def install_plugin(self, artifact="", name="No name", version="dev", hash=False): + return await self.context.plugin_browser.request_plugin_install( + artifact=artifact, + name=name, + version=version, + hash=hash + ) + async def confirm_plugin_install(self, request_id): return await self.context.plugin_browser.confirm_plugin_install(request_id) def cancel_plugin_install(self, request_id): return self.context.plugin_browser.cancel_plugin_install(request_id) + async def uninstall_plugin(self, name): + return await self.context.plugin_browser.uninstall_plugin(name) + async def http_request(self, method="", url="", **kwargs): async with ClientSession() as web: async with web.request(method, url, ssl=helpers.get_ssl_context(), **kwargs) as res: @@ -74,12 +88,12 @@ class Utilities: return { "success": True, - "result" : result["result"]["result"].get("value") + "result": result["result"]["result"].get("value") } except Exception as e: return { - "success": False, - "result": e + "success": False, + "result": e } async def inject_css_into_tab(self, tab, style): @@ -104,7 +118,7 @@ class Utilities: return { "success": True, - "result" : css_id + "result": css_id } except Exception as e: return { diff --git a/frontend/src/components/settings/pages/general/Updater.tsx b/frontend/src/components/settings/pages/general/Updater.tsx index cb58b24c..9635162c 100644 --- a/frontend/src/components/settings/pages/general/Updater.tsx +++ b/frontend/src/components/settings/pages/general/Updater.tsx @@ -17,46 +17,38 @@ function PatchNotesModal({ versionInfo, closeModal }: { versionInfo: VerInfo | n return ( <Focusable onCancelButton={closeModal}> <Carousel - fnItemRenderer={(id: number, ...args: any[]) => { - console.log(args, versionInfo); - return ( - <Focusable - onActivate={() => {}} - style={{ - marginTop: '40px', - height: 'calc( 100% - 40px )', - overflowY: 'scroll', - display: 'flex', - justifyContent: 'center', - margin: '40px', - }} - > - <div> - <h1>{versionInfo?.all?.[id]?.name}</h1> - {versionInfo?.all?.[id]?.body ? ( - <Suspense fallback={<Spinner style={{ width: '24', height: '24' }} />}> - <MarkdownRenderer>{versionInfo.all[id].body}</MarkdownRenderer> - </Suspense> - ) : ( - 'no patch notes for this version' - )} - </div> - </Focusable> - ); - }} - fnGetId={(id) => { - return id; - }} + fnItemRenderer={(id: number) => ( + <Focusable + onActivate={() => {}} + style={{ + marginTop: '40px', + height: 'calc( 100% - 40px )', + overflowY: 'scroll', + display: 'flex', + justifyContent: 'center', + margin: '40px', + }} + > + <div> + <h1>{versionInfo?.all?.[id]?.name}</h1> + {versionInfo?.all?.[id]?.body ? ( + <Suspense fallback={<Spinner style={{ width: '24', height: '24' }} />}> + <MarkdownRenderer>{versionInfo.all[id].body}</MarkdownRenderer> + </Suspense> + ) : ( + 'no patch notes for this version' + )} + </div> + </Focusable> + )} + fnGetId={(id) => id} nNumItems={versionInfo?.all?.length} nHeight={window.innerHeight - 150} nItemHeight={window.innerHeight - 200} nItemMarginX={0} initialColumn={0} autoFocus={true} - fnGetColumnWidth={(...args: any[]) => { - console.log('cw', args); - return window.innerWidth; - }} + fnGetColumnWidth={() => window.innerWidth} /> </Focusable> ); @@ -98,8 +90,8 @@ export default function UpdaterSettings() { return ( <> <Field - onOptionsActionDescription="Patch Notes" - onOptionsButton={showPatchNotes} + onOptionsActionDescription={versionInfo?.all ? 'Patch Notes' : undefined} + onOptionsButton={versionInfo?.all ? showPatchNotes : undefined} label="Updates" description={ versionInfo && ( diff --git a/frontend/src/plugin-loader.tsx b/frontend/src/plugin-loader.tsx index 661a2f67..85b03704 100644 --- a/frontend/src/plugin-loader.tsx +++ b/frontend/src/plugin-loader.tsx @@ -150,16 +150,7 @@ class PluginLoader extends Logger { showModal( <ModalRoot onOK={async () => { - const formData = new FormData(); - formData.append('name', name); - await fetch('http://localhost:1337/browser/uninstall_plugin', { - method: 'POST', - body: formData, - credentials: 'include', - headers: { - Authentication: window.deckyAuthToken, - }, - }); + await this.callServerMethod('uninstall_plugin', { name }); }} onCancel={() => { // do nothing diff --git a/frontend/src/store.tsx b/frontend/src/store.tsx index 3e9d6823..12c8972d 100644 --- a/frontend/src/store.tsx +++ b/frontend/src/store.tsx @@ -42,17 +42,10 @@ export function getLegacyPluginList(): Promise<LegacyStorePlugin[]> { } export async function installFromURL(url: string) { - const formData = new FormData(); const splitURL = url.split('/'); - formData.append('name', splitURL[splitURL.length - 1].replace('.zip', '')); - formData.append('artifact', url); - await fetch('http://localhost:1337/browser/install_plugin', { - method: 'POST', - body: formData, - credentials: 'include', - headers: { - Authentication: window.deckyAuthToken, - }, + await window.DeckyPluginLoader.callServerMethod('install_plugin', { + name: splitURL[splitURL.length - 1].replace('.zip', ''), + artifact: url, }); } @@ -60,18 +53,11 @@ export function requestLegacyPluginInstall(plugin: LegacyStorePlugin, selectedVe showModal( <ModalRoot onOK={() => { - const formData = new FormData(); - formData.append('name', plugin.artifact); - formData.append('artifact', `https://github.com/${plugin.artifact}/archive/refs/tags/${selectedVer}.zip`); - formData.append('version', selectedVer); - formData.append('hash', plugin.versions[selectedVer]); - fetch('http://localhost:1337/browser/install_plugin', { - method: 'POST', - body: formData, - credentials: 'include', - headers: { - Authentication: window.deckyAuthToken, - }, + window.DeckyPluginLoader.callServerMethod('install_plugin', { + name: plugin.artifact, + artifact: `https://github.com/${plugin.artifact}/archive/refs/tags/${selectedVer}.zip`, + version: selectedVer, + hash: plugin.versions[selectedVer], }); }} onCancel={() => { @@ -89,18 +75,11 @@ export function requestLegacyPluginInstall(plugin: LegacyStorePlugin, selectedVe } export async function requestPluginInstall(plugin: string, selectedVer: StorePluginVersion) { - const formData = new FormData(); - formData.append('name', plugin); - formData.append('artifact', `https://cdn.tzatzikiweeb.moe/file/steam-deck-homebrew/versions/${selectedVer.hash}.zip`); - formData.append('version', selectedVer.name); - formData.append('hash', selectedVer.hash); - await fetch('http://localhost:1337/browser/install_plugin', { - method: 'POST', - body: formData, - credentials: 'include', - headers: { - Authentication: window.deckyAuthToken, - }, + await window.DeckyPluginLoader.callServerMethod('install_plugin', { + name: plugin, + artifact: `https://cdn.tzatzikiweeb.moe/file/steam-deck-homebrew/versions/${selectedVer.hash}.zip`, + version: selectedVer.name, + hash: selectedVer.hash, }); } |
