Skip to content
Draft
4 changes: 4 additions & 0 deletions docs/js_plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions docs/plugin_dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
60 changes: 58 additions & 2 deletions helper/js/murkmod.js
Original file line number Diff line number Diff line change
Expand Up @@ -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...',
Expand Down Expand Up @@ -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) {
Expand All @@ -564,7 +608,7 @@ document.addEventListener("DOMContentLoaded", function () {
}
}
card.innerHTML = `<div class="card-title">${PLUGIN_NAME}<div>
<div class="card-author">By ${PLUGIN_AUTHOR} - Bash</div>
<div class="card-author">By ${PLUGIN_AUTHOR} - v${PLUGIN_VERSION} - Bash</div>
<div class="card-description">${PLUGIN_DESCRIPTION}</div>
<button id="card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn">${install_btn}</button>`;
document.querySelector(`#card-${file.name.split(".")[0]}-${file.name.split(".")[1]}-installbtn`).addEventListener("click", function(){
Expand All @@ -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`);
Expand Down Expand Up @@ -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 = `<div class="card-title">${PLUGIN_NAME}<div>
<div class="card-author">By ${PLUGIN_AUTHOR} - JavaScript</div>
<div class="card-description">${PLUGIN_DESCRIPTION}</div>
Expand Down
24 changes: 21 additions & 3 deletions mush.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;;
Expand All @@ -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"

Expand All @@ -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
}
Expand Down Expand Up @@ -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
Expand Down