mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-05 20:03:48 +00:00
Update script version and improve loading logic
Updated version to 1.3 and last updated date to 14/03/2025. Removed dependency on metadata.json and improved script loading and error handling.
This commit is contained in:
@@ -6,8 +6,8 @@
|
|||||||
# Author : MacRimi
|
# Author : MacRimi
|
||||||
# Copyright : (c) 2024 MacRimi
|
# Copyright : (c) 2024 MacRimi
|
||||||
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
|
# License : (GPL-3.0) (https://github.com/MacRimi/ProxMenux/blob/main/LICENSE)
|
||||||
# Version : 1.2
|
# Version : 1.3
|
||||||
# Last Updated: 14/11/2025
|
# Last Updated: 14/03/2025
|
||||||
# ==========================================================
|
# ==========================================================
|
||||||
# Description:
|
# Description:
|
||||||
# This script provides a simple and efficient way to access and execute Proxmox VE scripts
|
# This script provides a simple and efficient way to access and execute Proxmox VE scripts
|
||||||
@@ -33,8 +33,9 @@ load_language
|
|||||||
initialize_cache
|
initialize_cache
|
||||||
# ==========================================================
|
# ==========================================================
|
||||||
|
|
||||||
|
# New unified cache — categories and mirror URLs are embedded,
|
||||||
|
# metadata.json is no longer needed.
|
||||||
HELPERS_JSON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/refs/heads/main/json/helpers_cache.json"
|
HELPERS_JSON_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/refs/heads/main/json/helpers_cache.json"
|
||||||
METADATA_URL="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/frontend/public/json/metadata.json"
|
|
||||||
|
|
||||||
for cmd in curl jq dialog; do
|
for cmd in curl jq dialog; do
|
||||||
if ! command -v "$cmd" >/dev/null; then
|
if ! command -v "$cmd" >/dev/null; then
|
||||||
@@ -44,63 +45,78 @@ for cmd in curl jq dialog; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
CACHE_JSON=$(curl -s "$HELPERS_JSON_URL")
|
CACHE_JSON=$(curl -s "$HELPERS_JSON_URL")
|
||||||
META_JSON=$(curl -s "$METADATA_URL")
|
|
||||||
|
|
||||||
|
# Validate that the JSON loaded correctly
|
||||||
|
if ! echo "$CACHE_JSON" | jq -e 'if type == "array" and length > 0 then true else false end' >/dev/null 2>&1; then
|
||||||
|
dialog --title "Helper Scripts" \
|
||||||
|
--msgbox "Error: Could not load helpers cache.\nCheck your internet connection and try again.\n\nURL: $HELPERS_JSON_URL" 10 70
|
||||||
|
exec bash "$LOCAL_SCRIPTS/menus/main_menu.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Build category map directly from the cache (id → name).
|
||||||
|
# Uses transpose to pair categories[] and category_names[] arrays — no
|
||||||
|
# dependency on metadata.json, which no longer exists upstream.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
declare -A CATEGORY_NAMES
|
declare -A CATEGORY_NAMES
|
||||||
while read -r id name; do
|
while IFS=$'\t' read -r id name; do
|
||||||
CATEGORY_NAMES[$id]="$name"
|
[[ -n "$id" && -n "$name" ]] && CATEGORY_NAMES["$id"]="$name"
|
||||||
done < <(echo "$META_JSON" | jq -r '.categories[] | "\(.id)\t\(.name)"')
|
done < <(echo "$CACHE_JSON" | jq -r '
|
||||||
|
[.[] | [.categories, .category_names] | transpose[] | @tsv]
|
||||||
|
| unique[]')
|
||||||
|
|
||||||
|
# Count scripts per category (deduplicated by slug)
|
||||||
declare -A CATEGORY_COUNT
|
declare -A CATEGORY_COUNT
|
||||||
for id in $(echo "$CACHE_JSON" | jq -r '
|
while read -r id; do
|
||||||
group_by(.slug) | map(.[0])[] | .categories[]'); do
|
|
||||||
((CATEGORY_COUNT[$id]++))
|
((CATEGORY_COUNT[$id]++))
|
||||||
done
|
done < <(echo "$CACHE_JSON" | jq -r '
|
||||||
|
group_by(.slug) | map(.[0])[] | .categories[]')
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Type label — updated to match new type values (lxc instead of ct)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
get_type_label() {
|
get_type_label() {
|
||||||
local type="$1"
|
local type="$1"
|
||||||
case "$type" in
|
case "$type" in
|
||||||
ct) echo $'\Z1LXC\Zn' ;;
|
lxc) echo $'\Z1LXC\Zn' ;;
|
||||||
vm) echo $'\Z4VM\Zn' ;;
|
vm) echo $'\Z4VM\Zn' ;;
|
||||||
pve) echo $'\Z3PVE\Zn' ;;
|
pve) echo $'\Z3PVE\Zn' ;;
|
||||||
addon) echo $'\Z2ADDON\Zn' ;;
|
addon) echo $'\Z2ADDON\Zn' ;;
|
||||||
*) echo $'\Z7GEN\Zn' ;;
|
turnkey) echo $'\Z5TK\Zn' ;;
|
||||||
|
*) echo $'\Z7GEN\Zn' ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Download and execute a script URL, with optional mirror fallback
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
download_script() {
|
download_script() {
|
||||||
local url="$1"
|
local url="$1"
|
||||||
local fallback_pve="${url/misc\/tools\/pve}"
|
|
||||||
local fallback_addon="${url/misc\/tools\/addon}"
|
|
||||||
local fallback_copydata="${url/misc\/tools\/copy-data}"
|
|
||||||
|
|
||||||
if curl --silent --head --fail "$url" >/dev/null; then
|
if curl --silent --head --fail "$url" >/dev/null; then
|
||||||
bash <(curl -s "$url")
|
bash <(curl -s "$url")
|
||||||
elif curl --silent --head --fail "$fallback_pve" >/dev/null; then
|
|
||||||
bash <(curl -s "$fallback_pve")
|
|
||||||
elif curl --silent --head --fail "$fallback_addon" >/dev/null; then
|
|
||||||
bash <(curl -s "$fallback_addon")
|
|
||||||
elif curl --silent --head --fail "$fallback_copydata" >/dev/null; then
|
|
||||||
bash <(curl -s "$fallback_copydata")
|
|
||||||
else
|
else
|
||||||
dialog --title "Helper Scripts" --msgbox "Error: Failed to download the script." 12 70
|
dialog --title "Helper Scripts" --msgbox "$(translate "Error: Failed to download the script.")" 8 70
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_TO_MAIN=false
|
RETURN_TO_MAIN=false
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Format default credentials for display
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
format_credentials() {
|
format_credentials() {
|
||||||
local script_info="$1"
|
local script_info="$1"
|
||||||
local credentials_info=""
|
local credentials_info=""
|
||||||
|
|
||||||
local has_credentials
|
local has_credentials
|
||||||
has_credentials=$(echo "$script_info" | base64 --decode | jq -r 'has("default_credentials")')
|
has_credentials=$(echo "$script_info" | base64 --decode | jq -r 'has("default_credentials")')
|
||||||
|
|
||||||
if [[ "$has_credentials" == "true" ]]; then
|
if [[ "$has_credentials" == "true" ]]; then
|
||||||
local username password
|
local username password
|
||||||
username=$(echo "$script_info" | base64 --decode | jq -r '.default_credentials.username // empty')
|
username=$(echo "$script_info" | base64 --decode | jq -r '.default_credentials.username // empty')
|
||||||
password=$(echo "$script_info" | base64 --decode | jq -r '.default_credentials.password // empty')
|
password=$(echo "$script_info" | base64 --decode | jq -r '.default_credentials.password // empty')
|
||||||
|
|
||||||
if [[ -n "$username" && -n "$password" ]]; then
|
if [[ -n "$username" && -n "$password" ]]; then
|
||||||
credentials_info="Username: $username | Password: $password"
|
credentials_info="Username: $username | Password: $password"
|
||||||
elif [[ -n "$username" ]]; then
|
elif [[ -n "$username" ]]; then
|
||||||
@@ -109,30 +125,41 @@ format_credentials() {
|
|||||||
credentials_info="Password: $password"
|
credentials_info="Password: $password"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$credentials_info"
|
echo "$credentials_info"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Run a script identified by its slug.
|
||||||
|
#
|
||||||
|
# A slug can have multiple entries when a script supports several OS variants
|
||||||
|
# (e.g. Debian + Alpine). Each entry carries its own script_url / mirror and
|
||||||
|
# the os field already normalised to lowercase by generate_helpers_cache.py.
|
||||||
|
# The menu lets the user pick OS variant × source (GitHub / Mirror).
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
run_script_by_slug() {
|
run_script_by_slug() {
|
||||||
local slug="$1"
|
local slug="$1"
|
||||||
local -a script_infos
|
local -a script_infos
|
||||||
mapfile -t script_infos < <(echo "$CACHE_JSON" | jq -r --arg slug "$slug" '.[] | select(.slug == $slug) | @base64')
|
mapfile -t script_infos < <(echo "$CACHE_JSON" | jq -r --arg slug "$slug" \
|
||||||
|
'.[] | select(.slug == $slug) | @base64')
|
||||||
|
|
||||||
if [[ ${#script_infos[@]} -eq 0 ]]; then
|
if [[ ${#script_infos[@]} -eq 0 ]]; then
|
||||||
dialog --title "Helper Scripts" --msgbox "Error: No script data found for slug: $slug" 8 60
|
dialog --title "Helper Scripts" \
|
||||||
|
--msgbox "$(translate "Error: No script data found for slug:") $slug" 8 60
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
decode() {
|
decode() { echo "$1" | base64 --decode | jq -r "$2"; }
|
||||||
echo "$1" | base64 --decode | jq -r "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
local first="${script_infos[0]}"
|
local first="${script_infos[0]}"
|
||||||
local name desc notes
|
local name desc notes port website
|
||||||
name=$(decode "$first" ".name")
|
name=$(decode "$first" ".name")
|
||||||
desc=$(decode "$first" ".desc")
|
desc=$(decode "$first" ".desc")
|
||||||
notes=$(decode "$first" ".notes | join(\"\n\")")
|
notes=$(decode "$first" '.notes | join("\n")')
|
||||||
|
port=$(decode "$first" ".port // 0")
|
||||||
|
website=$(decode "$first" ".website // empty")
|
||||||
|
|
||||||
|
# Build notes block
|
||||||
local notes_dialog=""
|
local notes_dialog=""
|
||||||
if [[ -n "$notes" ]]; then
|
if [[ -n "$notes" ]]; then
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
@@ -145,18 +172,21 @@ run_script_by_slug() {
|
|||||||
local credentials
|
local credentials
|
||||||
credentials=$(format_credentials "$first")
|
credentials=$(format_credentials "$first")
|
||||||
|
|
||||||
local msg="\Zb\Z4Descripción:\Zn\n$desc"
|
# Build info message
|
||||||
[[ -n "$notes_dialog" ]] && msg+="\n\n\Zb\Z4Notes:\Zn\n$notes_dialog"
|
local msg="\Zb\Z4$(translate "Description"):\Zn\n$desc"
|
||||||
[[ -n "$credentials" ]] && msg+="\n\n\Zb\Z4Default Credentials:\Zn\n$credentials"
|
[[ -n "$notes_dialog" ]] && msg+="\n\n\Zb\Z4$(translate "Notes"):\Zn\n$notes_dialog"
|
||||||
|
[[ -n "$credentials" ]] && msg+="\n\n\Zb\Z4$(translate "Default Credentials"):\Zn\n$credentials"
|
||||||
# Add separator before menu options
|
[[ "$port" -gt 0 ]] && msg+="\n\n\Zb\Z4$(translate "Default Port"):\Zn $port"
|
||||||
|
[[ -n "$website" ]] && msg+="\n\Zb\Z4$(translate "Website"):\Zn $website"
|
||||||
|
|
||||||
msg+="\n\n$(translate "Choose how to run the script:"):"
|
msg+="\n\n$(translate "Choose how to run the script:"):"
|
||||||
|
|
||||||
|
# Build menu: one or two entries per script_info (GH + optional Mirror)
|
||||||
declare -a MENU_OPTS=()
|
declare -a MENU_OPTS=()
|
||||||
local idx=0
|
local idx=0
|
||||||
for s in "${script_infos[@]}"; do
|
for s in "${script_infos[@]}"; do
|
||||||
local os script_url script_url_mirror script_name
|
local os script_url script_url_mirror script_name
|
||||||
os=$(decode "$s" ".os // empty")
|
os=$(decode "$s" '.os // empty')
|
||||||
[[ -z "$os" ]] && os="$(translate "default")"
|
[[ -z "$os" ]] && os="$(translate "default")"
|
||||||
script_name=$(decode "$s" ".name")
|
script_name=$(decode "$s" ".name")
|
||||||
script_url=$(decode "$s" ".script_url")
|
script_url=$(decode "$s" ".script_url")
|
||||||
@@ -196,7 +226,8 @@ run_script_by_slug() {
|
|||||||
if [[ -n "$mirror_url" ]]; then
|
if [[ -n "$mirror_url" ]]; then
|
||||||
download_script "$mirror_url"
|
download_script "$mirror_url"
|
||||||
else
|
else
|
||||||
dialog --title "Helper Scripts" --msgbox "$(translate "Mirror URL not available for this script.")" 8 60
|
dialog --title "Helper Scripts" \
|
||||||
|
--msgbox "$(translate "Mirror URL not available for this script.")" 8 60
|
||||||
RETURN_TO_MAIN=false
|
RETURN_TO_MAIN=false
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
@@ -206,10 +237,10 @@ run_script_by_slug() {
|
|||||||
echo
|
echo
|
||||||
|
|
||||||
if [[ -n "$desc" || -n "$notes" || -n "$credentials" ]]; then
|
if [[ -n "$desc" || -n "$notes" || -n "$credentials" ]]; then
|
||||||
echo -e "$TAB\e[1;36mScript Information:\e[0m"
|
echo -e "$TAB\e[1;36m$(translate "Script Information"):\e[0m"
|
||||||
|
|
||||||
if [[ -n "$notes" ]]; then
|
if [[ -n "$notes" ]]; then
|
||||||
echo -e "$TAB\e[1;33mNotes:\e[0m"
|
echo -e "$TAB\e[1;33m$(translate "Notes"):\e[0m"
|
||||||
while IFS= read -r line; do
|
while IFS= read -r line; do
|
||||||
[[ -z "$line" ]] && continue
|
[[ -z "$line" ]] && continue
|
||||||
echo -e "$TAB• $line"
|
echo -e "$TAB• $line"
|
||||||
@@ -218,26 +249,30 @@ run_script_by_slug() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "$credentials" ]]; then
|
if [[ -n "$credentials" ]]; then
|
||||||
echo -e "$TAB\e[1;32mDefault Credentials:\e[0m"
|
echo -e "$TAB\e[1;32m$(translate "Default Credentials"):\e[0m"
|
||||||
echo "$TAB$credentials"
|
echo "$TAB$credentials"
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
msg_success "Press Enter to return to the main menu..."
|
msg_success "$(translate "Press Enter to return to the main menu...")"
|
||||||
read -r
|
read -r
|
||||||
RETURN_TO_MAIN=true
|
RETURN_TO_MAIN=true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Search / filter scripts by name or description
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
search_and_filter_scripts() {
|
search_and_filter_scripts() {
|
||||||
local search_term=""
|
local search_term=""
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
search_term=$(dialog --inputbox "Enter search term (leave empty to show all scripts):" \
|
search_term=$(dialog --inputbox \
|
||||||
8 65 "$search_term" 3>&1 1>&2 2>&3)
|
"$(translate "Enter search term (leave empty to show all scripts):"):" \
|
||||||
|
8 65 "$search_term" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
[[ $? -ne 0 ]] && return
|
[[ $? -ne 0 ]] && return
|
||||||
|
|
||||||
local filtered_json
|
local filtered_json
|
||||||
if [[ -z "$search_term" ]]; then
|
if [[ -z "$search_term" ]]; then
|
||||||
filtered_json="$CACHE_JSON"
|
filtered_json="$CACHE_JSON"
|
||||||
@@ -250,12 +285,14 @@ search_and_filter_scripts() {
|
|||||||
(.desc | ascii_downcase | contains($term))
|
(.desc | ascii_downcase | contains($term))
|
||||||
)]')
|
)]')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local count
|
local count
|
||||||
count=$(echo "$filtered_json" | jq 'group_by(.slug) | length')
|
count=$(echo "$filtered_json" | jq 'group_by(.slug) | length')
|
||||||
|
|
||||||
if [[ $count -eq 0 ]]; then
|
if [[ "$count" -eq 0 ]]; then
|
||||||
dialog --msgbox "No scripts found for: '$search_term'\n\nTry a different search term." 8 50
|
dialog --msgbox \
|
||||||
|
"$(translate "No scripts found for:") '$search_term'\n\n$(translate "Try a different search term.")" \
|
||||||
|
8 50
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -263,43 +300,41 @@ search_and_filter_scripts() {
|
|||||||
declare -A index_to_slug
|
declare -A index_to_slug
|
||||||
local menu_items=()
|
local menu_items=()
|
||||||
local i=1
|
local i=1
|
||||||
|
|
||||||
while IFS=$'\t' read -r slug name type; do
|
while IFS=$'\t' read -r slug name type; do
|
||||||
index_to_slug[$i]="$slug"
|
index_to_slug[$i]="$slug"
|
||||||
local label
|
local label
|
||||||
label=$(get_type_label "$type")
|
label=$(get_type_label "$type")
|
||||||
local padded_name
|
local padded_name
|
||||||
padded_name=$(printf "%-42s" "$name")
|
padded_name=$(printf "%-42s" "$name")
|
||||||
local entry="$padded_name $label"
|
menu_items+=("$i" "$padded_name $label")
|
||||||
menu_items+=("$i" "$entry")
|
|
||||||
((i++))
|
((i++))
|
||||||
done < <(echo "$filtered_json" | jq -r '
|
done < <(echo "$filtered_json" | jq -r '
|
||||||
group_by(.slug) | map(.[0]) | sort_by(.name)[] | [.slug, .name, .type] | @tsv')
|
group_by(.slug) | map(.[0]) | sort_by(.name)[]
|
||||||
|
| [.slug, .name, .type] | @tsv')
|
||||||
|
|
||||||
menu_items+=("" "")
|
menu_items+=("" "")
|
||||||
menu_items+=("new_search" "New Search")
|
menu_items+=("new_search" "$(translate "New Search")")
|
||||||
menu_items+=("show_all" "Show All Scripts")
|
menu_items+=("show_all" "$(translate "Show All Scripts")")
|
||||||
|
|
||||||
local title="Search Results"
|
local title
|
||||||
if [[ -n "$search_term" ]]; then
|
if [[ -n "$search_term" ]]; then
|
||||||
title="Search Results for: '$search_term' ($count found)"
|
title="$(translate "Search Results for:") '$search_term' ($count $(translate "found"))"
|
||||||
else
|
else
|
||||||
title="All Available Scripts ($count total)"
|
title="$(translate "All Available Scripts") ($count $(translate "total"))"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local selected
|
local selected
|
||||||
selected=$(dialog --colors --backtitle "ProxMenux" \
|
selected=$(dialog --colors --backtitle "ProxMenux" \
|
||||||
--title "$title" \
|
--title "$title" \
|
||||||
--menu "Select a script or action:" \
|
--menu "$(translate "Select a script or action:"):" \
|
||||||
22 75 15 "${menu_items[@]}" 3>&1 1>&2 2>&3)
|
22 75 15 "${menu_items[@]}" 3>&1 1>&2 2>&3)
|
||||||
|
|
||||||
if [[ $? -ne 0 ]]; then
|
[[ $? -ne 0 ]] && return
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$selected" in
|
case "$selected" in
|
||||||
"new_search")
|
"new_search")
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
"show_all")
|
"show_all")
|
||||||
search_term=""
|
search_term=""
|
||||||
@@ -308,7 +343,7 @@ search_and_filter_scripts() {
|
|||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
"back"|"")
|
"back"|"")
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if [[ -n "${index_to_slug[$selected]}" ]]; then
|
if [[ -n "${index_to_slug[$selected]}" ]]; then
|
||||||
@@ -321,48 +356,64 @@ search_and_filter_scripts() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Main loop — category list built from embedded category data.
|
||||||
|
# We map scriptcatXXXXX IDs to short numeric indices so dialog doesn't show
|
||||||
|
# the long ID string as the visible tag in the menu column.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
while true; do
|
while true; do
|
||||||
MENU_ITEMS=()
|
MENU_ITEMS=()
|
||||||
|
MENU_ITEMS+=("search" "$(translate "Search/Filter Scripts")")
|
||||||
MENU_ITEMS+=("search" "Search/Filter Scripts")
|
|
||||||
MENU_ITEMS+=("" "")
|
MENU_ITEMS+=("" "")
|
||||||
|
|
||||||
for id in $(printf "%s\n" "${!CATEGORY_COUNT[@]}" | sort -n); do
|
# Map scriptcatXXXXX IDs to short numeric indices (1, 2, 3…) so dialog
|
||||||
|
# doesn't render the long ID string as the visible tag column.
|
||||||
|
declare -A CAT_IDX_TO_ID
|
||||||
|
local_idx=1
|
||||||
|
for id in $(printf "%s\n" "${!CATEGORY_COUNT[@]}" | sort); do
|
||||||
|
CAT_IDX_TO_ID[$local_idx]="$id"
|
||||||
name="${CATEGORY_NAMES[$id]:-Category $id}"
|
name="${CATEGORY_NAMES[$id]:-Category $id}"
|
||||||
count="${CATEGORY_COUNT[$id]}"
|
count="${CATEGORY_COUNT[$id]}"
|
||||||
padded_name=$(printf "%-35s" "$name")
|
padded_name=$(printf "%-35s" "$name")
|
||||||
padded_count=$(printf "(%2d)" "$count")
|
padded_count=$(printf "(%2d)" "$count")
|
||||||
MENU_ITEMS+=("$id" "$padded_name $padded_count")
|
MENU_ITEMS+=("$local_idx" "$padded_name $padded_count")
|
||||||
|
((local_idx++))
|
||||||
done
|
done
|
||||||
|
|
||||||
SELECTED=$(dialog --backtitle "ProxMenux" --title "Proxmox VE Helper-Scripts" --menu \
|
SELECTED_IDX=$(dialog --backtitle "ProxMenux" \
|
||||||
"Select a category or search for scripts:" 20 70 14 \
|
--title "Proxmox VE Helper-Scripts" \
|
||||||
"${MENU_ITEMS[@]}" 3>&1 1>&2 2>&3) || {
|
--menu "$(translate "Select a category or search for scripts:"):" \
|
||||||
dialog --clear --title "ProxMenux" \
|
20 70 14 "${MENU_ITEMS[@]}" 3>&1 1>&2 2>&3) || {
|
||||||
--msgbox "\n\n$(translate "Visit the website to discover more scripts, stay updated with the latest updates, and support the project:")\n\nhttps://community-scripts.github.io/ProxmoxVE" 15 70
|
dialog --clear --title "ProxMenux" \
|
||||||
|
--msgbox "\n\n$(translate "Visit the website to discover more scripts, stay updated with the latest updates, and support the project:")\n\nhttps://community-scripts.github.io/ProxmoxVE" 15 70
|
||||||
exec bash "$LOCAL_SCRIPTS/menus/main_menu.sh"
|
exec bash "$LOCAL_SCRIPTS/menus/main_menu.sh"
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ "$SELECTED" == "search" ]]; then
|
if [[ "$SELECTED_IDX" == "search" ]]; then
|
||||||
search_and_filter_scripts
|
search_and_filter_scripts
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Resolve numeric index back to the real category ID
|
||||||
|
SELECTED="${CAT_IDX_TO_ID[$SELECTED_IDX]}"
|
||||||
|
[[ -z "$SELECTED" ]] && continue
|
||||||
|
|
||||||
|
# ---- Scripts within the selected category --------------------------------
|
||||||
while true; do
|
while true; do
|
||||||
declare -A INDEX_TO_SLUG
|
declare -A INDEX_TO_SLUG
|
||||||
SCRIPTS=()
|
SCRIPTS=()
|
||||||
i=1
|
i=1
|
||||||
|
|
||||||
while IFS=$'\t' read -r slug name type; do
|
while IFS=$'\t' read -r slug name type; do
|
||||||
INDEX_TO_SLUG[$i]="$slug"
|
INDEX_TO_SLUG[$i]="$slug"
|
||||||
label=$(get_type_label "$type")
|
label=$(get_type_label "$type")
|
||||||
padded_name=$(printf "%-42s" "$name")
|
padded_name=$(printf "%-42s" "$name")
|
||||||
entry="$padded_name $label"
|
SCRIPTS+=("$i" "$padded_name $label")
|
||||||
SCRIPTS+=("$i" "$entry")
|
|
||||||
((i++))
|
((i++))
|
||||||
done < <(echo "$CACHE_JSON" | jq -r --argjson id "$SELECTED" '
|
done < <(echo "$CACHE_JSON" | jq -r --arg id "$SELECTED" '
|
||||||
[
|
[
|
||||||
.[]
|
.[]
|
||||||
| select(.categories | index($id))
|
| select(.categories | index($id))
|
||||||
| {slug, name, type}
|
| {slug, name, type}
|
||||||
]
|
]
|
||||||
| group_by(.slug)
|
| group_by(.slug)
|
||||||
@@ -371,13 +422,14 @@ while true; do
|
|||||||
| [.slug, .name, .type]
|
| [.slug, .name, .type]
|
||||||
| @tsv')
|
| @tsv')
|
||||||
|
|
||||||
SCRIPT_INDEX=$(dialog --colors --backtitle "ProxMenux" --title "Scripts in ${CATEGORY_NAMES[$SELECTED]}" --menu \
|
SCRIPT_INDEX=$(dialog --colors --backtitle "ProxMenux" \
|
||||||
"Choose a script to execute:" 20 70 14 \
|
--title "$(translate "Scripts in") ${CATEGORY_NAMES[$SELECTED]}" \
|
||||||
"${SCRIPTS[@]}" 3>&1 1>&2 2>&3) || break
|
--menu "$(translate "Choose a script to execute:"):" \
|
||||||
|
20 70 14 "${SCRIPTS[@]}" 3>&1 1>&2 2>&3) || break
|
||||||
|
|
||||||
SCRIPT_SELECTED="${INDEX_TO_SLUG[$SCRIPT_INDEX]}"
|
SCRIPT_SELECTED="${INDEX_TO_SLUG[$SCRIPT_INDEX]}"
|
||||||
run_script_by_slug "$SCRIPT_SELECTED"
|
run_script_by_slug "$SCRIPT_SELECTED"
|
||||||
|
|
||||||
[[ "$RETURN_TO_MAIN" == true ]] && { RETURN_TO_MAIN=false; break; }
|
[[ "$RETURN_TO_MAIN" == true ]] && { RETURN_TO_MAIN=false; break; }
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user