LibrePortal/scripts/docker/app/functions/function_app_tool.sh
librelad 898068a390 refactor(apps): make app tools + helpers fully self-contained per app
Each app now carries everything under containers/<app>/: Tools-tab actions in
tools/ (declaration <app>.tools.json + function <app>_<tool_id>.sh) and logic
helpers in scripts/ (e.g. <app>_auth.sh). The container scan live-sources every
.sh under the app (maxdepth 3, prunes only resources/) and webui_tools.sh
auto-merges the .tools.json, so an app is a true drop-in — no central edit, no
array regen.

- Empty the central webui_tools.sh heredoc; all 34 tools across 11 apps now
  come from per-app declarations (verified byte-identical to the old output).
- Retire the orphaned mattermost tool scripts to scripts/unused (there is no
  containers/mattermost; its install fn already lived in unused).
- Update the dispatch comment/error path, the auth-adapter doc, and
  DEVELOPMENT.md to the new convention.
- Regenerate static arrays (files_app.sh no longer lists app/containers/*).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-25 22:45:33 +01:00

76 lines
2.4 KiB
Bash

#!/bin/bash
# Per-app "tools" dispatcher.
#
# Each container/<app>/<app>.sh that exposes Tools-tab actions defines a
# function named `<app>Tool` (e.g. `gluetunTool`) that takes two args:
# $1 = tool id (matches an entry in <app>/<app>.tools.json)
# $2 = pipe-encoded args string from the modal, e.g. "duration=5|mode=fast"
#
# Tool args parsing helper: see toolArgsGet below.
dockerAppRunTool()
{
local app_name="$1"
local tool_name="$2"
local tool_args="$3"
# One-file-per-tool convention: tool id `<verb>_<noun>` resolves to
# function `app<AppName><PascalCaseToolId>`. Each tool lives at
# containers/<app>/tools/<app>_<tool_id>.sh (live-sourced by the container scan).
#
# Examples:
# gluetun + refresh_providers → appGluetunRefreshProviders
# nextcloud + reset_password → appNextcloudResetPassword
local app_name_ucfirst="$(tr '[:lower:]' '[:upper:]' <<< ${app_name:0:1})${app_name:1}"
local tool_pascal=""
local _word
local IFS='_'
for _word in $tool_name; do
tool_pascal+="$(tr '[:lower:]' '[:upper:]' <<< ${_word:0:1})${_word:1}"
done
unset IFS
local toolFuncName="app${app_name_ucfirst}${tool_pascal}"
if ! declare -f "$toolFuncName" >/dev/null 2>&1; then
isError "App '$app_name' has no tool '$tool_name' (missing function $toolFuncName — expected in containers/$app_name/tools/${app_name}_${tool_name}.sh)."
return 1
fi
initializeAppVariables "$app_name"
isHeader "Running tool '$tool_name' for $app_name"
"$toolFuncName" "$tool_args"
local tool_rc=$?
# Refresh apps.json so the WebUI sees any CFG_* the tool just wrote.
# Targeted patch (jq) instead of full regen — ~30x faster.
if declare -F webuiPatchAppConfigJson >/dev/null 2>&1; then
webuiPatchAppConfigJson "$app_name" >/dev/null 2>&1 || true
elif declare -F webuiGenerateLibrePortalConfig >/dev/null 2>&1; then
webuiGenerateLibrePortalConfig >/dev/null 2>&1 || true
fi
return $tool_rc
}
# Read a single value out of the pipe-encoded args string. Usage:
# local val
# val=$(toolArgsGet "$tool_args" "duration")
toolArgsGet()
{
local args="$1"
local key="$2"
local pair value
IFS='|' read -ra _pairs <<< "$args"
for pair in "${_pairs[@]}"; do
if [[ "$pair" == "$key="* ]]; then
value="${pair#${key}=}"
printf '%s' "$value"
return 0
fi
done
return 1
}