Compare commits

...

7 Commits

Author SHA1 Message Date
AAGaming e6cc4bba5c hotfix: change store URL in service file 2022-06-28 13:01:21 -04:00
Liam Dawe 1199c080bc Update README.md, password is needed (#70)
* Update README.md

There is no password by default, so people need to set one before running that script.

* Update README.md

add the guide for password
2022-06-06 14:35:56 -07:00
Jonas Dellinger 414e0da2f3 Fix hot-reload when there are subdirs (#56) 2022-05-11 02:11:14 +03:00
tza cb9b888dc6 Merge branch 'main' of https://github.com/SteamDeckHomebrew/PluginLoader 2022-05-10 23:17:12 +03:00
tza f3ab0f5989 Plugin store button now uses built-in browser 2022-05-10 23:17:09 +03:00
marios e132aba0f8 Fixed race condition pr 2022-05-10 21:11:51 +03:00
tza 0d0e57e35a Added store button 2022-05-10 20:31:39 +03:00
8 changed files with 60 additions and 20 deletions
+2 -1
View File
@@ -8,7 +8,8 @@
3. Scroll the sidebar all the way down and click on `Developer` 3. Scroll the sidebar all the way down and click on `Developer`
4. Under Miscellaneous, enable `CEF Remote Debugging` 4. Under Miscellaneous, enable `CEF Remote Debugging`
5. Click on the `STEAM` button and select `Power` -> `Switch to Desktop` 5. Click on the `STEAM` button and select `Power` -> `Switch to Desktop`
6. Open a terminal and paste the following command into it: 6. Make sure you have a password set with the "passwd" command in terminal to install it ([YouTube Guide](https://www.youtube.com/watch?v=1vOMYGj22rQ)).
7. Open a terminal and paste the following command into it:
- For users: - For users:
- `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/main/dist/install_release.sh | sh` - `curl -L https://github.com/SteamDeckHomebrew/PluginLoader/raw/main/dist/install_release.sh | sh`
- For developers: - For developers:
+1
View File
@@ -40,6 +40,7 @@ Restart=always
ExecStart=/home/deck/homebrew/services/PluginLoader ExecStart=/home/deck/homebrew/services/PluginLoader
WorkingDirectory=/home/deck/homebrew/services WorkingDirectory=/home/deck/homebrew/services
Environment=STORE_URL=https://plugins.deckbrew.xyz
Environment=PLUGIN_PATH=/home/deck/homebrew/plugins Environment=PLUGIN_PATH=/home/deck/homebrew/plugins
[Install] [Install]
+1
View File
@@ -30,6 +30,7 @@ User=root
Restart=always Restart=always
ExecStart=/home/deck/homebrew/services/PluginLoader ExecStart=/home/deck/homebrew/services/PluginLoader
WorkingDirectory=/home/deck/homebrew/services WorkingDirectory=/home/deck/homebrew/services
Environment=STORE_URL=https://plugins.deckbrew.xyz
Environment=PLUGIN_PATH=/home/deck/homebrew/plugins Environment=PLUGIN_PATH=/home/deck/homebrew/plugins
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
+2 -2
View File
@@ -1,4 +1,4 @@
from injector import get_tab from injector import get_tab, inject_to_tab
from logging import getLogger from logging import getLogger
from os import path, rename from os import path, rename
from shutil import rmtree from shutil import rmtree
@@ -26,7 +26,7 @@ class PluginBrowser:
server_instance.add_routes([ server_instance.add_routes([
web.post("/browser/install_plugin", self.install_plugin), web.post("/browser/install_plugin", self.install_plugin),
web.get("/browser/iframe", self.redirect_to_store) web.get("/browser/redirect", self.redirect_to_store),
]) ])
def _unzip_to_plugin_dir(self, zip, name, hash): def _unzip_to_plugin_dir(self, zip, name, hash):
+11 -11
View File
@@ -6,6 +6,8 @@ from asyncio import Queue
from os import path, listdir from os import path, listdir
from logging import getLogger from logging import getLogger
from time import time from time import time
from genericpath import exists
from pathlib import Path
from injector import get_tabs, get_tab from injector import get_tabs, get_tab
from plugin import PluginWrapper from plugin import PluginWrapper
@@ -18,6 +20,12 @@ class FileChangeHandler(FileSystemEventHandler):
self.plugin_path = plugin_path self.plugin_path = plugin_path
self.queue = queue self.queue = queue
def maybe_reload(self, src_path):
plugin_dir = Path(path.relpath(src_path, self.plugin_path)).parts[0]
self.logger.info(path.join(self.plugin_path, plugin_dir, "plugin.json"))
if exists(path.join(self.plugin_path, plugin_dir, "plugin.json")):
self.queue.put_nowait((path.join(self.plugin_path, plugin_dir, "main.py"), plugin_dir, True))
def on_created(self, event): def on_created(self, event):
src_path = event.src_path src_path = event.src_path
if "__pycache__" in src_path: if "__pycache__" in src_path:
@@ -27,13 +35,8 @@ class FileChangeHandler(FileSystemEventHandler):
if path.isdir(src_path): if path.isdir(src_path):
return return
# get the directory name of the plugin so that we can find its "main.py" and reload it; the
# file that changed is not necessarily the one that needs to be reloaded
self.logger.debug(f"file created: {src_path}") self.logger.debug(f"file created: {src_path}")
rel_path = path.relpath(src_path, path.commonprefix([self.plugin_path, src_path])) self.maybe_reload(src_path)
plugin_dir = path.split(rel_path)[0]
main_file_path = path.join(self.plugin_path, plugin_dir, "main.py")
self.queue.put_nowait((main_file_path, plugin_dir, True))
def on_modified(self, event): def on_modified(self, event):
src_path = event.src_path src_path = event.src_path
@@ -44,11 +47,8 @@ class FileChangeHandler(FileSystemEventHandler):
if path.isdir(src_path): if path.isdir(src_path):
return return
# get the directory name of the plugin so that we can find its "main.py" and reload it; the
# file that changed is not necessarily the one that needs to be reloaded
self.logger.debug(f"file modified: {src_path}") self.logger.debug(f"file modified: {src_path}")
plugin_dir = path.split(path.relpath(src_path, path.commonprefix([self.plugin_path, src_path])))[0] self.maybe_reload(src_path)
self.queue.put_nowait((path.join(self.plugin_path, plugin_dir, "main.py"), plugin_dir, True))
class Loader: class Loader:
def __init__(self, server_instance, plugin_path, loop, live_reload=False) -> None: def __init__(self, server_instance, plugin_path, loop, live_reload=False) -> None:
@@ -121,7 +121,7 @@ class Loader:
return await self.callsigns[callsign].execute_method(method_name, kwargs) return await self.callsigns[callsign].execute_method(method_name, kwargs)
async def get_steam_resource(self, request): async def get_steam_resource(self, request):
tab = (await get_tabs())[0] tab = await get_tab("QuickAccess")
try: try:
return web.Response(text=await tab.get_steam_resource(f"https://steamloopback.host/{request.match_info['path']}"), content_type="text/html") return web.Response(text=await tab.get_steam_resource(f"https://steamloopback.host/{request.match_info['path']}"), content_type="text/html")
except Exception as e: except Exception as e:
+3 -3
View File
@@ -7,7 +7,7 @@ CONFIG = {
"server_port": int(getenv("SERVER_PORT", "1337")), "server_port": int(getenv("SERVER_PORT", "1337")),
"live_reload": getenv("LIVE_RELOAD", "1") == "1", "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")],
"store_url": getenv("STORE_URL", "https://plugins.deckbrew.xyz"), "store_url": getenv("STORE_URL", "https://beta.deckbrew.xyz"),
"log_base_events": getenv("LOG_BASE_EVENTS", "0")=="1" "log_base_events": getenv("LOG_BASE_EVENTS", "0")=="1"
} }
@@ -96,7 +96,7 @@ class PluginManager:
"id": 1, "id": 1,
"method": "Runtime.evaluate", "method": "Runtime.evaluate",
"params": { "params": {
"expression": f"resolveMethodCall({call_id}, {r})", "expression": f"resolveMethodCall('{call_id}', {r})",
"userGesture": True "userGesture": True
} }
}, receive=False) }, receive=False)
@@ -141,4 +141,4 @@ class PluginManager:
return run_app(self.web_app, host=CONFIG["server_host"], port=CONFIG["server_port"], loop=self.loop, access_log=None) return run_app(self.web_app, host=CONFIG["server_host"], port=CONFIG["server_port"], loop=self.loop, access_log=None)
if __name__ == "__main__": if __name__ == "__main__":
PluginManager().run() PluginManager().run()
+25 -2
View File
@@ -53,8 +53,22 @@ function addPluginInstallPrompt(artifact, version, request_id) {
</svg> </svg>
`; `;
const SHOP_ICON = `
<button
class="DialogButton _DialogLayout Secondary basicdialog_Button_1Ievp Focusable"
style="width: auto; padding-left: 10px; padding-right: 10px; margin-right: 1rem; margin-left: auto; padding-top: 3px;"
id="open_shop_button"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bag-fill" viewBox="0 0 16 16">
<path d="M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5z"/>
</svg>
</button>
`
function createTitle(text) { function createTitle(text) {
return `<div id="plugin_title" class="quickaccessmenu_Title_34nl5">${text}</div>`; return `
<div class="quickaccessmenu_Title_34nl5"><div id="plugin_title">${text}</div>${SHOP_ICON}</div>
`;
} }
function createPluginList() { function createPluginList() {
@@ -79,11 +93,20 @@ function addPluginInstallPrompt(artifact, version, request_id) {
inject(); inject();
document.getElementById("plugin_title").onclick = function() { document.getElementById("plugin_title").onclick = function() {
reloadIframe(); reloadIframe();
document.getElementById("plugin_title").innerText = "Plugins"; document.getElementById("plugin_title").innerText = `Plugins`;
document.getElementById("open_shop_button").style.display = 'block';
}
document.getElementById("open_shop_button").onclick = function(ev) {
console.debug(JSON.stringify({
"id": 1,
"method": "open_plugin_store",
"args": {}
}));
} }
window.onmessage = function(ev) { window.onmessage = function(ev) {
let title = ev.data; let title = ev.data;
if (title.startsWith("PLUGIN_LOADER__")) { if (title.startsWith("PLUGIN_LOADER__")) {
document.getElementById("open_shop_button").style.display = 'none';
document.getElementById("plugin_title").innerHTML = ` document.getElementById("plugin_title").innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left-square-fill" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left-square-fill" viewBox="0 0 16 16">
<path d="M16 14a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12zm-4.5-6.5H5.707l2.147-2.146a.5.5 0 1 0-.708-.708l-3 3a.5.5 0 0 0 0 .708l3 3a.5.5 0 0 0 .708-.708L5.707 8.5H11.5a.5.5 0 0 0 0-1z"/> <path d="M16 14a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12zm-4.5-6.5H5.707l2.147-2.146a.5.5 0 1 0-.708-.708l-3 3a.5.5 0 0 0 0 .708l3 3a.5.5 0 0 0 .708-.708L5.707 8.5H11.5a.5.5 0 0 0 0-1z"/>
+15 -1
View File
@@ -11,7 +11,8 @@ class Utilities:
"confirm_plugin_install": self.confirm_plugin_install, "confirm_plugin_install": self.confirm_plugin_install,
"execute_in_tab": self.execute_in_tab, "execute_in_tab": self.execute_in_tab,
"inject_css_into_tab": self.inject_css_into_tab, "inject_css_into_tab": self.inject_css_into_tab,
"remove_css_from_tab": self.remove_css_from_tab "remove_css_from_tab": self.remove_css_from_tab,
"open_plugin_store": self.open_plugin_store
} }
async def confirm_plugin_install(self, request_id): async def confirm_plugin_install(self, request_id):
@@ -104,3 +105,16 @@ class Utilities:
"success": False, "success": False,
"result": e "result": e
} }
async def open_plugin_store(self):
await inject_to_tab("SP", """
(function() {
wpRequire = webpackJsonp.push([[], { get_require: (mod, _exports, wpRequire) => mod.exports = wpRequire }, [["get_require"]]]);
const all = () => Object.keys(wpRequire.c).map((x) => wpRequire.c[x].exports).filter((x) => x);
router = all().map(m => {
if (typeof m !== "object") return undefined;
for (let prop in m) { if (m[prop]?.Navigate) return m[prop]}
}).find(x => x)
router.NavigateToExternalWeb("http://127.0.0.1:1337/browser/redirect")
})();
""")