summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorAAGaming <aa@mail.catvibers.me>2022-06-30 16:04:29 -0400
committerAAGaming <aa@mail.catvibers.me>2022-06-30 16:04:29 -0400
commitd72f364a8d032ca53c35c22c8dbe01ba354629df (patch)
tree9cc49e3854feed4579a9bf170c975daa8e1c5258 /backend
parentda0f7dd337502476a625709775f07ef9ec4f0c44 (diff)
downloaddecky-loader-d72f364a8d032ca53c35c22c8dbe01ba354629df.tar.gz
decky-loader-d72f364a8d032ca53c35c22c8dbe01ba354629df.zip
backwards-compatible plugin store, legacy plugin library
Diffstat (limited to 'backend')
-rw-r--r--backend/browser.py28
-rw-r--r--backend/legacy/library.js78
-rw-r--r--backend/loader.py6
-rw-r--r--backend/main.py6
4 files changed, 96 insertions, 22 deletions
diff --git a/backend/browser.py b/backend/browser.py
index f2325aff..37099e19 100644
--- a/backend/browser.py
+++ b/backend/browser.py
@@ -12,21 +12,20 @@ from hashlib import sha256
from subprocess import Popen
class PluginInstallContext:
- def __init__(self, gh_url, version, hash) -> None:
- self.gh_url = gh_url
+ def __init__(self, artifact, name, version, hash) -> None:
+ self.artifact = artifact
+ self.name = name
self.version = version
self.hash = hash
class PluginBrowser:
- def __init__(self, plugin_path, server_instance, store_url) -> None:
+ def __init__(self, plugin_path, server_instance) -> None:
self.log = getLogger("browser")
self.plugin_path = plugin_path
- self.store_url = store_url
self.install_requests = {}
server_instance.add_routes([
- web.post("/browser/install_plugin", self.install_plugin),
- web.get("/browser/redirect", self.redirect_to_store)
+ web.post("/browser/install_plugin", self.install_plugin)
])
def _unzip_to_plugin_dir(self, zip, name, hash):
@@ -40,12 +39,12 @@ class PluginBrowser:
Popen(["chmod", "-R", "555", self.plugin_path])
return True
- async def _install(self, name, version, hash):
+ async def _install(self, artifact, name, version, hash):
rmtree(path.join(self.plugin_path, name), ignore_errors=True)
self.log.info(f"Installing {name} (Version: {version})")
async with ClientSession() as client:
- self.log.debug(f"Fetching {name}")
- res = await client.get(name)
+ self.log.debug(f"Fetching {artifact}")
+ res = await client.get(artifact)
if res.status == 200:
self.log.debug("Got 200. Reading...")
data = await res.read()
@@ -67,24 +66,21 @@ class PluginBrowser:
else:
self.log.fatal(f"Could not fetch from URL. {await res.text()}")
- async def redirect_to_store(self, request):
- return web.Response(status=302, headers={"Location": self.store_url})
-
async def install_plugin(self, request):
data = await request.post()
- get_event_loop().create_task(self.request_plugin_install(data.get("name", "No name"), data.get("version", "dev"), data.get("hash", False)))
+ 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, name, version, hash):
+ async def request_plugin_install(self, artifact, name, version, hash):
request_id = str(time())
- self.install_requests[request_id] = PluginInstallContext(name, version, hash)
+ 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.gh_url, 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) \ No newline at end of file
diff --git a/backend/legacy/library.js b/backend/legacy/library.js
new file mode 100644
index 00000000..f9dfe699
--- /dev/null
+++ b/backend/legacy/library.js
@@ -0,0 +1,78 @@
+class PluginEventTarget extends EventTarget { }
+method_call_ev_target = new PluginEventTarget();
+
+window.addEventListener("message", function(evt) {
+ let ev = new Event(evt.data.call_id);
+ ev.data = evt.data.result;
+ method_call_ev_target.dispatchEvent(ev);
+}, false);
+
+async function call_server_method(method_name, arg_object={}) {
+ const response = await fetch(`http://127.0.0.1:1337/methods/${method_name}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(arg_object),
+ });
+
+ const dta = await response.json();
+ if (!dta.success) throw dta.result;
+ return dta.result;
+}
+
+// Source: https://stackoverflow.com/a/2117523 Thanks!
+function uuidv4() {
+ return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
+ );
+}
+
+async function fetch_nocors(url, request={}) {
+ let args = { method: "POST", headers: {}, body: "" };
+ request = {...args, ...request};
+ request.url = url;
+ request.data = request.body;
+ delete request.body; //maintain api-compatibility with fetch
+ return await call_server_method("http_request", request);
+}
+
+async function call_plugin_method(method_name, arg_object={}) {
+ if (plugin_name == undefined)
+ throw new Error("Plugin methods can only be called from inside plugins (duh)");
+ const response = await fetch(`http://127.0.0.1:1337/plugins/${plugin_name}/methods/${method_name}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ args: arg_object,
+ }),
+ });
+
+ const dta = await response.json();
+ if (!dta.success) throw dta.result;
+ return dta.result;
+}
+
+async function execute_in_tab(tab, run_async, code) {
+ return await call_server_method("execute_in_tab", {
+ 'tab': tab,
+ 'run_async': run_async,
+ 'code': code
+ });
+}
+
+async function inject_css_into_tab(tab, style) {
+ return await call_server_method("inject_css_into_tab", {
+ 'tab': tab,
+ 'style': style
+ });
+}
+
+async function remove_css_from_tab(tab, css_id) {
+ return await call_server_method("remove_css_from_tab", {
+ 'tab': tab,
+ 'css_id': css_id
+ });
+} \ No newline at end of file
diff --git a/backend/loader.py b/backend/loader.py
index c420fafe..3f5d1ab8 100644
--- a/backend/loader.py
+++ b/backend/loader.py
@@ -116,7 +116,7 @@ class Loader:
self.logger.info(f"Plugin {plugin.name} is passive")
self.plugins[plugin.name] = plugin.start()
self.logger.info(f"Loaded {plugin.name}")
- self.loop.create_task(self.dispatch_plugin(plugin.name))
+ self.loop.create_task(self.dispatch_plugin(plugin.name if not plugin.legacy else "$LEGACY_" + plugin.name))
except Exception as e:
self.logger.error(f"Could not load {file}. {e}")
print_exc()
@@ -168,8 +168,8 @@ class Loader:
with open(path.join(self.plugin_path, plugin.plugin_directory, plugin.main_view_html), 'r') as template:
template_data = template.read()
ret = f"""
- <script src="/static/legacy-library.js"></script>
- <script>const plugin_name = '{plugin.name}' </script>
+ <script src="/legacy/library.js"></script>
+ <script>window.plugin_name = '{plugin.name}' </script>
<base href="http://127.0.0.1:1337/plugins/plugin_resource/{plugin.name}/">
{template_data}
"""
diff --git a/backend/main.py b/backend/main.py
index f942ee29..afd3cc21 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -9,8 +9,7 @@ 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")],
- "store_url": getenv("STORE_URL", "https://beta.deckbrew.xyz")
+ "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")
@@ -44,7 +43,7 @@ class PluginManager:
allow_headers="*")
})
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, CONFIG["store_url"])
+ self.plugin_browser = PluginBrowser(CONFIG["plugin_path"], self.web_app)
self.utilities = Utilities(self)
jinja_setup(self.web_app)
@@ -57,6 +56,7 @@ class PluginManager:
for route in list(self.web_app.router.routes()):
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'))])
def exception_handler(self, loop, context):
if context["message"] == "Unclosed connection":