mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-06-28 04:06:54 +00:00
291 lines
8.2 KiB
Bash
291 lines
8.2 KiB
Bash
#!/bin/bash
|
|
|
|
# ==========================================================
|
|
# ProxMenu - A menu-driven script for Proxmox VE management
|
|
# ==========================================================
|
|
# Author : MacRimi
|
|
# Copyright : (c) 2024 MacRimi
|
|
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE)
|
|
# Version : 1.1
|
|
# Last Updated: 04/06/2025
|
|
# ==========================================================
|
|
# Description:
|
|
# This script provides a simple and efficient way to access and execute Proxmox VE scripts
|
|
# from the Community Scripts project (https://community-scripts.github.io/ProxmoxVE/).
|
|
#
|
|
# It serves as a convenient tool to run key automation scripts that simplify system management,
|
|
# continuing the great work and legacy of tteck in making Proxmox VE more accessible.
|
|
# A streamlined solution for executing must-have tools in Proxmox VE.
|
|
# ==========================================================
|
|
|
|
|
|
# Configuration ============================================
|
|
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
|
|
BASE_DIR="/usr/local/share/proxmenux"
|
|
UTILS_FILE="$BASE_DIR/utils.sh"
|
|
VENV_PATH="/opt/googletrans-env"
|
|
|
|
if [[ -f "$UTILS_FILE" ]]; then
|
|
source "$UTILS_FILE"
|
|
fi
|
|
|
|
load_language
|
|
initialize_cache
|
|
# ==========================================================
|
|
|
|
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
|
|
if ! command -v "$cmd" >/dev/null; then
|
|
echo "Missing required command: $cmd"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
|
|
CACHE_JSON=$(curl -s "$HELPERS_JSON_URL")
|
|
META_JSON=$(curl -s "$METADATA_URL")
|
|
|
|
|
|
declare -A CATEGORY_NAMES
|
|
while read -r id name; do
|
|
CATEGORY_NAMES[$id]="$name"
|
|
done < <(echo "$META_JSON" | jq -r '.categories[] | "\(.id)\t\(.name)"')
|
|
|
|
|
|
declare -A CATEGORY_COUNT
|
|
for id in $(echo "$CACHE_JSON" | jq -r '.[].categories[]'); do
|
|
((CATEGORY_COUNT[$id]++))
|
|
done
|
|
|
|
|
|
get_type_label() {
|
|
local type="$1"
|
|
case "$type" in
|
|
ct) echo $'\Z1LXC\Zn' ;;
|
|
vm) echo $'\Z4VM\Zn' ;;
|
|
pve) echo $'\Z3PVE\Zn' ;;
|
|
addon) echo $'\Z2ADDON\Zn' ;;
|
|
*) echo $'\Z7GEN\Zn' ;;
|
|
esac
|
|
}
|
|
|
|
|
|
download_script() {
|
|
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
|
|
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
|
|
dialog --title "Helper Scripts" --msgbox "Error: Failed to download the script." 12 70
|
|
fi
|
|
}
|
|
|
|
|
|
RETURN_TO_MAIN=false
|
|
|
|
|
|
run_script_by_slug() {
|
|
local slug="$1"
|
|
local script_info
|
|
script_info=$(echo "$CACHE_JSON" | jq -r --arg slug "$slug" '.[] | select(.slug == $slug) | @base64')
|
|
|
|
decode() {
|
|
echo "$1" | base64 --decode | jq -r "$2"
|
|
}
|
|
|
|
local name desc script_url notes
|
|
name=$(decode "$script_info" ".name")
|
|
desc=$(decode "$script_info" ".desc")
|
|
script_url=$(decode "$script_info" ".script_url")
|
|
notes=$(decode "$script_info" ".notes | join(\"\n• \" )")
|
|
|
|
local msg="\Zb\Z1$name\Zn\n\n$desc"
|
|
[[ -n "$notes" ]] && msg+="\n\n\ZbNotes:\Zn\n• $notes"
|
|
|
|
dialog --clear --colors --backtitle "ProxMenux" --title "$name" --yesno "$msg\n\nExecute this script?" 20 80
|
|
if [[ $? -eq 0 ]]; then
|
|
download_script "$script_url"
|
|
echo
|
|
echo
|
|
msg_success "Press Enter to return to the main menu..."
|
|
read -r
|
|
|
|
RETURN_TO_MAIN=true
|
|
fi
|
|
}
|
|
|
|
|
|
search_and_filter_scripts() {
|
|
local search_term=""
|
|
|
|
while true; do
|
|
|
|
search_term=$(dialog --inputbox "Enter search term (leave empty to show all scripts):" \
|
|
8 65 "$search_term" 3>&1 1>&2 2>&3)
|
|
|
|
|
|
[[ $? -ne 0 ]] && return
|
|
|
|
|
|
local filtered_json
|
|
if [[ -z "$search_term" ]]; then
|
|
filtered_json="$CACHE_JSON"
|
|
else
|
|
local search_lower
|
|
search_lower=$(echo "$search_term" | tr '[:upper:]' '[:lower:]')
|
|
filtered_json=$(echo "$CACHE_JSON" | jq --arg term "$search_lower" '
|
|
[.[] | select(
|
|
(.name | ascii_downcase | contains($term)) or
|
|
(.desc | ascii_downcase | contains($term))
|
|
)]')
|
|
fi
|
|
|
|
|
|
local count
|
|
count=$(echo "$filtered_json" | jq length)
|
|
|
|
if [[ $count -eq 0 ]]; then
|
|
dialog --msgbox "No scripts found for: '$search_term'\n\nTry a different search term." 8 50
|
|
continue
|
|
fi
|
|
|
|
|
|
while true; do
|
|
declare -A index_to_slug
|
|
local menu_items=()
|
|
local i=1
|
|
|
|
while IFS=$'\t' read -r slug name type; do
|
|
index_to_slug[$i]="$slug"
|
|
local label
|
|
label=$(get_type_label "$type")
|
|
local padded_name
|
|
padded_name=$(printf "%-42s" "$name")
|
|
local entry="$padded_name $label"
|
|
menu_items+=("$i" "$entry")
|
|
((i++))
|
|
done < <(echo "$filtered_json" | jq -r '
|
|
sort_by(.name)[] | [.slug, .name, .type] | @tsv')
|
|
|
|
|
|
menu_items+=("" "")
|
|
menu_items+=("new_search" "New Search")
|
|
menu_items+=("show_all" "Show All Scripts")
|
|
|
|
|
|
local title="Search Results"
|
|
if [[ -n "$search_term" ]]; then
|
|
title="Search Results for: '$search_term' ($count found)"
|
|
else
|
|
title="All Available Scripts ($count total)"
|
|
fi
|
|
|
|
|
|
local selected
|
|
selected=$(dialog --colors --backtitle "ProxMenux" \
|
|
--title "$title" \
|
|
--menu "Select a script or action:" \
|
|
22 75 15 "${menu_items[@]}" 3>&1 1>&2 2>&3)
|
|
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
|
|
return
|
|
fi
|
|
|
|
case "$selected" in
|
|
"new_search")
|
|
break
|
|
;;
|
|
"show_all")
|
|
search_term=""
|
|
filtered_json="$CACHE_JSON"
|
|
count=$(echo "$filtered_json" | jq length)
|
|
continue
|
|
;;
|
|
"back"|"")
|
|
return
|
|
;;
|
|
*)
|
|
|
|
if [[ -n "${index_to_slug[$selected]}" ]]; then
|
|
run_script_by_slug "${index_to_slug[$selected]}"
|
|
[[ "$RETURN_TO_MAIN" == true ]] && { RETURN_TO_MAIN=false; return; }
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
done
|
|
}
|
|
|
|
|
|
while true; do
|
|
MENU_ITEMS=()
|
|
|
|
|
|
MENU_ITEMS+=("search" "Search/Filter Scripts")
|
|
MENU_ITEMS+=("" "")
|
|
|
|
|
|
for id in $(printf "%s\n" "${!CATEGORY_COUNT[@]}" | sort -n); do
|
|
name="${CATEGORY_NAMES[$id]:-Category $id}"
|
|
count="${CATEGORY_COUNT[$id]}"
|
|
padded_name=$(printf "%-35s" "$name")
|
|
padded_count=$(printf "(%2d)" "$count")
|
|
MENU_ITEMS+=("$id" "$padded_name $padded_count")
|
|
done
|
|
|
|
SELECTED=$(dialog --backtitle "ProxMenux" --title "Proxmox VE Helper-Scripts" --menu \
|
|
"Select a category or search for scripts:" 20 70 14 \
|
|
"${MENU_ITEMS[@]}" 3>&1 1>&2 2>&3) || {
|
|
dialog --title "Proxmox VE Helper-Scripts" \
|
|
--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
|
|
|
|
clear
|
|
break
|
|
}
|
|
|
|
|
|
if [[ "$SELECTED" == "search" ]]; then
|
|
search_and_filter_scripts
|
|
continue
|
|
fi
|
|
|
|
|
|
while true; do
|
|
declare -A INDEX_TO_SLUG
|
|
SCRIPTS=()
|
|
i=1
|
|
while IFS=$'\t' read -r slug name type; do
|
|
INDEX_TO_SLUG[$i]="$slug"
|
|
label=$(get_type_label "$type")
|
|
padded_name=$(printf "%-42s" "$name")
|
|
entry="$padded_name $label"
|
|
SCRIPTS+=("$i" "$entry")
|
|
((i++))
|
|
done < <(echo "$CACHE_JSON" | jq -r --argjson id "$SELECTED" \
|
|
'[.[] | select(.categories | index($id)) | {slug, name, type}] | sort_by(.name)[] | [.slug, .name, .type] | @tsv')
|
|
|
|
SCRIPT_INDEX=$(dialog --colors --backtitle "ProxMenux" --title "Scripts in ${CATEGORY_NAMES[$SELECTED]}" --menu \
|
|
"Choose a script to execute:" 20 70 14 \
|
|
"${SCRIPTS[@]}" 3>&1 1>&2 2>&3) || break
|
|
|
|
SCRIPT_SELECTED="${INDEX_TO_SLUG[$SCRIPT_INDEX]}"
|
|
run_script_by_slug "$SCRIPT_SELECTED"
|
|
|
|
|
|
[[ "$RETURN_TO_MAIN" == true ]] && { RETURN_TO_MAIN=false; break; }
|
|
done
|
|
done |