diff --git a/docs/js_plugins.md b/docs/js_plugins.md index 6b547d8..467278b 100644 --- a/docs/js_plugins.md +++ b/docs/js_plugins.md @@ -16,6 +16,8 @@ var PLUGIN_FUNCTION = "Click me!!!"; var PLUGIN_DESCRIPTION = "An example JS plugin" var PLUGIN_AUTHOR = "Me!"; var PLUGIN_VERSION = 1; +// optionally: +var PLUGIN_DEPENDENCIES = []; function plugin_init() { // this is run on plugin initialization, when a helper tab is opened @@ -29,6 +31,8 @@ function plugin_main() { } ``` +Optionally, you can add an array of strings, `PLUGIN_DEPENDENCIES`, to provide a list of plugins published in murkmod that your plugin requires to run correctly. Plugin dependencies are resolved recursively, so be careful about creating deep dependency trees that may increase installation times. + Otherwise, publishing of a JS plugin is identical to that of a bash plugin - fork the murkmod repo, add the file to `/plugins`, and make a PR. ## APIs and Methods diff --git a/docs/plugin_dev.md b/docs/plugin_dev.md index 1f1daad..258143f 100644 --- a/docs/plugin_dev.md +++ b/docs/plugin_dev.md @@ -17,6 +17,12 @@ echo "Hello, World!" Of course, you should change this to match your plugin. Every time you update your plugin, you should increment `PLUGIN_VERSION`. Everything below the initial variables, though, is what is executed when you run the plugin from the mush menu. +Optionally, you can specify a array of plugin names, `PLUGIN_DEPENDENCIES`. These plugins will be installed automatically when this plugin is installed. + +```sh +PLUGIN_DEPENDENCIES=("plugin_1.sh" "plugin_2.sh") +``` + To add a plugin to this repository (for easy download from mush), just fork the repo, add the file in `/plugins/` and make a PR. I'll review it and merge it if it doesn't do anything malicious. The second comment at the top defines the type of the plugin. There are threeplugin types: diff --git a/helper/js/murkmod.js b/helper/js/murkmod.js index 091f897..c0100b8 100644 --- a/helper/js/murkmod.js +++ b/helper/js/murkmod.js @@ -513,6 +513,42 @@ document.addEventListener("DOMContentLoaded", function () { const match = script.match(regex); return match ? match[1] : null; }; + const extractValueUnquoted = (variable, script) => { + const regex = new RegExp(`${variable}=(.*?)\n`); + const match = script.match(regex); + return match ? match[1] : null; + }; + + function handle_js_dep(plugin) { + if (plugin.endsWith(".js")){ + fetch(`https://api.github.com/repos/rainestorme/murkmod/contents/plugins/${plugin}`) + .then(response => {return response.json()}) + .then(file => { + var file_content = atob(file.content); + var trimmed = { + "name": file.name, + "path": file.path, + "sha": file.sha, + "size": file.size, + "url": file.url, + "download_url": file.download_url, + "type": file.type, + }; + installed_plugins.push({ + file: trimmed, + text: file_content + }); + localStorage.setItem("plugins", JSON.stringify(installed_plugins)); + }); + } else { + window.run_task("114\n", "", "> (1-", function (output) { + if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { + window.send(`${plugin}\n`); + } + }, function () {}, false, ""); + } + } + document.querySelector("#store").addEventListener("click", function() { Swal.fire({ title: 'Loading plugin store...', @@ -554,7 +590,15 @@ document.addEventListener("DOMContentLoaded", function () { const PLUGIN_FUNCTION = extractValue("PLUGIN_FUNCTION", text); const PLUGIN_DESCRIPTION = extractValue("PLUGIN_DESCRIPTION", text); const PLUGIN_AUTHOR = extractValue("PLUGIN_AUTHOR", text); - console.log(PLUGIN_NAME, PLUGIN_FUNCTION, PLUGIN_DESCRIPTION, PLUGIN_AUTHOR); + const PLUGIN_VERSION = extractValueUnquoted("PLUGIN_VERSION", text); + var _PLUGIN_DEPENDENCIES = extractValueUnquoted("PLUGIN_DEPENDENCIES", text); + if (!_PLUGIN_DEPENDENCIES){ + _PLUGIN_DEPENDENCIES = "[]" + } else { + _PLUGIN_DEPENDENCIES = _PLUGIN_DEPENDENCIES.replace("(", "[").replace(")", "]").replace(" ", ", ") + } + const PLUGIN_DEPENDENCIES = JSON.parse(_PLUGIN_DEPENDENCIES); + console.log(PLUGIN_NAME, PLUGIN_FUNCTION, PLUGIN_DESCRIPTION, PLUGIN_AUTHOR, PLUGIN_DEPENDENCIES); var install_btn = "Install"; var installed = false; for (let i in window.legacy_plugins) { @@ -564,7 +608,7 @@ document.addEventListener("DOMContentLoaded", function () { } } card.innerHTML = `
${PLUGIN_NAME}
-
By ${PLUGIN_AUTHOR} - Bash
+
By ${PLUGIN_AUTHOR} - v${PLUGIN_VERSION} - Bash
${PLUGIN_DESCRIPTION}
`; document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).addEventListener("click", function(){ @@ -578,6 +622,13 @@ document.addEventListener("DOMContentLoaded", function () { }, false, ""); return; } + PLUGIN_DEPENDENCIES.forEach(plugin=>{ + window.run_task("114\n", "", "> (1-", function (output) { + if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { + window.send(`${plugin}\n`); + } + }, function () {}, false, ""); + }); window.run_task("114\n", "", "> (1-", function (output) { if (output.includes("Enter the name of a plugin (including the .sh) to install it (or q to quit):")) { window.send(`${file.name}\n`); @@ -605,6 +656,11 @@ document.addEventListener("DOMContentLoaded", function () { if (already_installed) { install_btn = "Uninstall"; } + if (typeof PLUGIN_DEPENDENCIES !== 'undefined') { + PLUGIN_DEPENDENCIES.forEach(plugin => { + handle_js_dep(plugin); + }); + } card.innerHTML = `
${PLUGIN_NAME}
By ${PLUGIN_AUTHOR} - JavaScript
${PLUGIN_DESCRIPTION}
diff --git a/mush.sh b/mush.sh index 6ca76bc..bb8e10e 100644 --- a/mush.sh +++ b/mush.sh @@ -166,7 +166,7 @@ EOF 24) runjob attempt_dev_install ;; 25) runjob do_updates && exit 0 ;; 26) runjob do_dev_updates && exit 0 ;; - 101) runjob hard_disable_nokill ;; + 101) runjob hard_disable_nokill ;; # anything prefixed with a 1 is for the helper extension, you can safely ignore these as a user 111) runjob hard_enable_nokill ;; 112) runjob ext_purge ;; 113) runjob list_plugins ;; @@ -178,6 +178,24 @@ EOF done } +do_install_plugin() { + local url=$1 + local filename="$(echo "${url}" | rev | cut -d/ -f1 | rev)" + if [ ! -f /mnt/stateful_partition/murkmod/plugins/$filename ]; then + doas "pushd /mnt/stateful_partition/murkmod/plugins + curl $url -O + chmod 775 /mnt/stateful_partition/murkmod/plugins/$filename + popd" > /dev/null + local dependencies=($(grep -o 'PLUGIN_DEPENDENCIES\+=([^)]*)' "/mnt/stateful_partition/murkmod/plugins/$filename" | sed 's/PLUGIN_DEPENDENCIES\+=//; s/[()]//g')) + for dep in "${dependencies[@]}"; do + local dep_fixed=$(echo "$dep" | tr -d '"') + echo "Installing $dep_fixed..." + do_install_plugin "https://raw.githubusercontent.com/rainestorme/murkmod/main/plugins/$dep_fixed" + done + fi + read -r -p "Press enter to continue." throwaway +} + install_plugin_legacy() { local raw_url="https://raw.githubusercontent.com/rainestorme/murkmod/main/plugins" @@ -193,7 +211,7 @@ install_plugin_legacy() { echo "Plugin not found" else echo "Installing..." - doas "pushd /mnt/stateful_partition/murkmod/plugins && curl https://raw.githubusercontent.com/rainestorme/murkmod/main/plugins/$plugin_name -O && popd" > /dev/null + do_install_plugin "https://raw.githubusercontent.com/rainestorme/murkmod/main/plugins/$plugin_name" echo "Installed $plugin_name" fi } @@ -480,7 +498,7 @@ install_plugins() { "") clear echo "Using URL: ${download_urls[$selected_option]}" echo "Installing plugin..." - doas "pushd /mnt/stateful_partition/murkmod/plugins && curl ${download_urls[$selected_option]} -O && popd" > /dev/null + do_install_plugin "${download_urls[$selected_option]}" echo "Done!" ;; esac