summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbotato <63275405+botatooo@users.noreply.github.com>2022-08-27 00:01:23 -0400
committerGitHub <noreply@github.com>2022-08-26 21:01:23 -0700
commitb7d7ca04e12690b5e65259c8806e5e895cdc16aa (patch)
tree4cca1b72b69622e536dbb1ba13656d39a9420685
parentd4d1c2bbabfcec3c62767e614c9d67f516938af2 (diff)
downloaddecky-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.py39
-rw-r--r--backend/main.py22
-rw-r--r--backend/utilities.py22
-rw-r--r--frontend/src/components/settings/pages/general/Updater.tsx64
-rw-r--r--frontend/src/plugin-loader.tsx11
-rw-r--r--frontend/src/store.tsx47
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,
});
}