Compare commits
7 Commits
86f3e9d133
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c1051226b | |||
| 9a096970c3 | |||
| b390872d27 | |||
| be6c7285b3 | |||
| f5121bc1c5 | |||
| 72cba64e23 | |||
| 797da9cf5b |
@@ -56,6 +56,7 @@ function helpme() {
|
|||||||
echo -e "\e[32m---------- My Scripts -----------\e[0m"
|
echo -e "\e[32m---------- My Scripts -----------\e[0m"
|
||||||
echo -e "myapps : Install Fedora apps"
|
echo -e "myapps : Install Fedora apps"
|
||||||
echo -e "phoneapps : Install mobile apps"
|
echo -e "phoneapps : Install mobile apps"
|
||||||
|
echo -e "caddy : Manage caddy configs"
|
||||||
echo -e "compress : Compress videos with handbrake"
|
echo -e "compress : Compress videos with handbrake"
|
||||||
echo -e "star-update : Update terminal from gitea"
|
echo -e "star-update : Update terminal from gitea"
|
||||||
echo -e "star-edit : Edit starship config"
|
echo -e "star-edit : Edit starship config"
|
||||||
@@ -63,10 +64,15 @@ function helpme() {
|
|||||||
echo -e "wii : Convert Wii games"
|
echo -e "wii : Convert Wii games"
|
||||||
echo -e "nds-patcher : Patches NDS ROMs"
|
echo -e "nds-patcher : Patches NDS ROMs"
|
||||||
echo -e "megadrive : Flashes Megadrive Carts"
|
echo -e "megadrive : Flashes Megadrive Carts"
|
||||||
|
echo -e "chd : Converts roms with CHDMAN"
|
||||||
echo -e ""
|
echo -e ""
|
||||||
echo -e "\e[32m--------- System Stats ----------\e[0m"
|
echo -e "\e[32m------------ System -------------\e[0m"
|
||||||
echo -e "kill [tab] : Show processes to Kill"
|
echo -e "kill [tab] : Show processes to Kill"
|
||||||
echo -e "btop : Show systems stats"
|
echo -e "btop : Show systems stats"
|
||||||
|
echo -e "rpmlist : List all RPM packages"
|
||||||
|
echo -e "sudo dnf remove *name : Remove a RPM package"
|
||||||
|
echo -e "flatpak list --app : List flatpak packages"
|
||||||
|
echo -e "flatremove app_id : Remove flatpak app"
|
||||||
echo -e ""
|
echo -e ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +97,8 @@ alias star-edit="nano ~/.config/starship.toml"
|
|||||||
alias ssh="kitty +kitten ssh"
|
alias ssh="kitty +kitten ssh"
|
||||||
alias pack="tar -cvJf" # pack compressed.tar.xz /folder/file1.txt /folder/folder2
|
alias pack="tar -cvJf" # pack compressed.tar.xz /folder/file1.txt /folder/folder2
|
||||||
alias unpack="tar -xvf"
|
alias unpack="tar -xvf"
|
||||||
|
alias flatremove="flatpak uninstall"
|
||||||
|
alias rpmlist="dnf list installed"
|
||||||
# Scripts
|
# Scripts
|
||||||
alias myapps="sudo -v && ~/.bash/scripts/fedora-apps.sh"
|
alias myapps="sudo -v && ~/.bash/scripts/fedora-apps.sh"
|
||||||
alias phoneapps="~/.bash/scripts/phone-apps.sh"
|
alias phoneapps="~/.bash/scripts/phone-apps.sh"
|
||||||
@@ -98,6 +106,8 @@ alias compress="~/.bash/scripts/compress.sh"
|
|||||||
alias wii="~/.bash/scripts/wii.sh"
|
alias wii="~/.bash/scripts/wii.sh"
|
||||||
alias nds-patcher="~/.bash/scripts/nds.sh"
|
alias nds-patcher="~/.bash/scripts/nds.sh"
|
||||||
alias megadrive="~/.bash/scripts/megadrive.sh"
|
alias megadrive="~/.bash/scripts/megadrive.sh"
|
||||||
|
alias chd="~/.bash/scripts/chd.sh"
|
||||||
|
alias caddy="~/.bash/scripts/caddy.sh"
|
||||||
|
|
||||||
export GSK_RENDERER=cairo
|
export GSK_RENDERER=cairo
|
||||||
eval "$(starship init bash)"
|
eval "$(starship init bash)"
|
||||||
|
|||||||
Executable
+372
@@ -0,0 +1,372 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# ─────────────────────────────────────────────────────────────
|
||||||
|
# Caddy Manager – gum-powered TUI
|
||||||
|
# SSH target : root@192.168.0.17
|
||||||
|
# Sites dir : ~/sites
|
||||||
|
# ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
SSH_TARGET="root@192.168.0.17"
|
||||||
|
SITES_DIR="~/sites"
|
||||||
|
RELOAD_CMD="docker exec -w /etc/caddy caddy caddy reload"
|
||||||
|
|
||||||
|
# ── Colour palette ────────────────────────────────────────────
|
||||||
|
ORANGE="#FF6B00"
|
||||||
|
ORANGE_DIM="#CC5500"
|
||||||
|
GREY_DARK="#2A2A2A"
|
||||||
|
GREY_MID="#4A4A4A"
|
||||||
|
GREY_LIGHT="#AAAAAA"
|
||||||
|
WHITE="#F5F5F5"
|
||||||
|
|
||||||
|
# ── Dependency check ─────────────────────────────────────────
|
||||||
|
if ! command -v gum &>/dev/null; then
|
||||||
|
echo "ERROR: 'gum' is not installed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v ssh &>/dev/null; then
|
||||||
|
echo "ERROR: 'ssh' is not installed."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── Helpers ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
draw_title() {
|
||||||
|
clear
|
||||||
|
gum style \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--border-foreground "$ORANGE" \
|
||||||
|
--border double \
|
||||||
|
--align center \
|
||||||
|
--width 50 \
|
||||||
|
--margin "1 2" \
|
||||||
|
--padding "1 4" \
|
||||||
|
--bold \
|
||||||
|
"⚙ CADDY MANAGER ⚙" \
|
||||||
|
"" \
|
||||||
|
"$(gum style --foreground "$GREY_LIGHT" --faint "$(date '+%a %d %b %Y %H:%M')")"
|
||||||
|
}
|
||||||
|
|
||||||
|
ssh_run() {
|
||||||
|
# Run a command on the remote host
|
||||||
|
ssh -o ConnectTimeout=10 -o BatchMode=yes "$SSH_TARGET" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_caddy() {
|
||||||
|
gum spin \
|
||||||
|
--spinner dot \
|
||||||
|
--title "Reloading Caddy..." \
|
||||||
|
--title.foreground "$ORANGE" \
|
||||||
|
-- ssh -o ConnectTimeout=10 -o BatchMode=yes "$SSH_TARGET" "$RELOAD_CMD"
|
||||||
|
}
|
||||||
|
|
||||||
|
press_enter() {
|
||||||
|
echo ""
|
||||||
|
gum style --foreground "$GREY_LIGHT" "Press Enter to return to the menu..."
|
||||||
|
read -r
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 1 – Add a new config ───────────────────────────────
|
||||||
|
|
||||||
|
add_config() {
|
||||||
|
draw_title
|
||||||
|
gum style \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--bold \
|
||||||
|
--margin "0 2" \
|
||||||
|
" ADD NEW SITE CONFIG"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Service name (used as filename)
|
||||||
|
SERVICE=$(gum input \
|
||||||
|
--prompt " Service name (filename): " \
|
||||||
|
--prompt.foreground "$ORANGE" \
|
||||||
|
--placeholder "e.g. nextcloud" \
|
||||||
|
--width 40 \
|
||||||
|
--cursor.foreground "$ORANGE")
|
||||||
|
|
||||||
|
[[ -z "$SERVICE" ]] && { gum style --foreground "red" " Aborted – no service name given."; press_enter; return; }
|
||||||
|
|
||||||
|
# Domain – type subdomain only, suffix appended automatically
|
||||||
|
SUBDOMAIN=$(gum input \
|
||||||
|
--prompt " Subdomain: " \
|
||||||
|
--prompt.foreground "$ORANGE" \
|
||||||
|
--placeholder "e.g. homarr (will become homarr.marlow.quest)" \
|
||||||
|
--width 50 \
|
||||||
|
--cursor.foreground "$ORANGE")
|
||||||
|
|
||||||
|
[[ -z "$SUBDOMAIN" ]] && { gum style --foreground "red" " Aborted – no domain given."; press_enter; return; }
|
||||||
|
|
||||||
|
# If they typed a full domain (contains a dot) use as-is, otherwise append suffix
|
||||||
|
if [[ "$SUBDOMAIN" == *.* ]]; then
|
||||||
|
DOMAIN="$SUBDOMAIN"
|
||||||
|
else
|
||||||
|
DOMAIN="${SUBDOMAIN}.marlow.quest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
gum style --foreground "$GREY_LIGHT" --margin "0 2" " → ${DOMAIN}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Upstream IP:port – pre-filled with common subnet prefix
|
||||||
|
UPSTREAM=$(gum input \
|
||||||
|
--prompt " Upstream IP:port: " \
|
||||||
|
--prompt.foreground "$ORANGE" \
|
||||||
|
--value "192.168.0." \
|
||||||
|
--width 40 \
|
||||||
|
--cursor.foreground "$ORANGE")
|
||||||
|
|
||||||
|
[[ -z "$UPSTREAM" ]] && { gum style --foreground "red" " Aborted – no upstream given."; press_enter; return; }
|
||||||
|
|
||||||
|
# TinyAuth?
|
||||||
|
echo ""
|
||||||
|
gum style --foreground "$GREY_LIGHT" --margin "0 2" " Include TinyAuth middleware?"
|
||||||
|
USE_TINYAUTH=$(gum choose \
|
||||||
|
--cursor "▶ " \
|
||||||
|
--cursor.foreground "$ORANGE" \
|
||||||
|
--selected.foreground "$ORANGE" \
|
||||||
|
--header " Select an option:" \
|
||||||
|
--header.foreground "$GREY_LIGHT" \
|
||||||
|
"No" "Yes")
|
||||||
|
|
||||||
|
# Build the Caddy config block
|
||||||
|
if [[ "$USE_TINYAUTH" == "Yes" ]]; then
|
||||||
|
CONFIG_BLOCK="${DOMAIN} {
|
||||||
|
import tinyauth
|
||||||
|
|
||||||
|
reverse_proxy ${UPSTREAM}
|
||||||
|
}"
|
||||||
|
else
|
||||||
|
CONFIG_BLOCK="${DOMAIN} {
|
||||||
|
reverse_proxy ${UPSTREAM}
|
||||||
|
}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Preview
|
||||||
|
echo ""
|
||||||
|
gum style \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--border normal \
|
||||||
|
--border-foreground "$GREY_MID" \
|
||||||
|
--padding "1 2" \
|
||||||
|
--margin "0 2" \
|
||||||
|
"$CONFIG_BLOCK"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
gum confirm \
|
||||||
|
--prompt.foreground "$ORANGE" \
|
||||||
|
--selected.background "$ORANGE" \
|
||||||
|
--selected.foreground "$GREY_DARK" \
|
||||||
|
" Write ${SERVICE}.conf to ${SITES_DIR} and reload Caddy?" \
|
||||||
|
|| { gum style --foreground "$GREY_LIGHT" " Cancelled."; press_enter; return; }
|
||||||
|
|
||||||
|
# Write file via SSH heredoc
|
||||||
|
ssh_run "cat > ${SITES_DIR}/${SERVICE}.conf" <<EOF
|
||||||
|
${CONFIG_BLOCK}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
gum style --foreground "green" " ✔ Config written to ${SITES_DIR}/${SERVICE}.conf"
|
||||||
|
|
||||||
|
reload_caddy && gum style --foreground "green" " ✔ Caddy reloaded successfully." \
|
||||||
|
|| gum style --foreground "red" " ✗ Caddy reload failed – check logs."
|
||||||
|
press_enter
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 2 – List / view configs ───────────────────────────
|
||||||
|
|
||||||
|
list_configs() {
|
||||||
|
while true; do
|
||||||
|
draw_title
|
||||||
|
gum style \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--bold \
|
||||||
|
--margin "0 2" \
|
||||||
|
" SITE CONFIGS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Fetch all file names
|
||||||
|
mapfile -t FILES < <(ssh_run "ls ${SITES_DIR}/" 2>/dev/null || true)
|
||||||
|
|
||||||
|
# Remove blank entries
|
||||||
|
CLEAN_FILES=()
|
||||||
|
for f in "${FILES[@]+"${FILES[@]}"}"; do
|
||||||
|
[[ -n "$f" ]] && CLEAN_FILES+=("$f")
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${#CLEAN_FILES[@]} -eq 0 ]]; then
|
||||||
|
gum style --foreground "$GREY_LIGHT" --margin "0 2" \
|
||||||
|
" No config files found in ${SITES_DIR}/"
|
||||||
|
press_enter
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse each file individually — build display arrays and a lookup map
|
||||||
|
T_NAME=()
|
||||||
|
T_DOMAIN=()
|
||||||
|
T_UPSTREAM=()
|
||||||
|
T_TINYAUTH=()
|
||||||
|
|
||||||
|
for FILE in "${CLEAN_FILES[@]}"; do
|
||||||
|
FILE_CONTENT=$(ssh_run "cat ${SITES_DIR}/${FILE}" 2>/dev/null || true)
|
||||||
|
|
||||||
|
DOMAIN=$(echo "$FILE_CONTENT" \
|
||||||
|
| grep -v '^\s*#' | grep -v '^\s*$' | grep -v '^\s' \
|
||||||
|
| grep '\.' | head -1 | awk '{print $1}' | tr -d '{}' || true)
|
||||||
|
[[ -z "$DOMAIN" ]] && DOMAIN="—"
|
||||||
|
|
||||||
|
UPSTREAM=$(echo "$FILE_CONTENT" \
|
||||||
|
| grep -i 'reverse_proxy' | awk '{print $2}' | head -1 || true)
|
||||||
|
[[ -z "$UPSTREAM" ]] && UPSTREAM="—"
|
||||||
|
|
||||||
|
if echo "$FILE_CONTENT" | grep -qi 'tinyauth' 2>/dev/null; then
|
||||||
|
TA="yes"
|
||||||
|
else
|
||||||
|
TA="no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
T_NAME+=("$FILE")
|
||||||
|
T_DOMAIN+=("$DOMAIN")
|
||||||
|
T_UPSTREAM+=("$UPSTREAM")
|
||||||
|
T_TINYAUTH+=("$TA")
|
||||||
|
done
|
||||||
|
|
||||||
|
# Write CSV to temp file (gum table needs a real fd, not a pipe)
|
||||||
|
TMPCSV=$(mktemp /tmp/caddy-XXXXXX.csv)
|
||||||
|
for i in "${!T_NAME[@]}"; do
|
||||||
|
printf '%s,%s,%s,%s\n' \
|
||||||
|
"${T_NAME[$i]}" "${T_DOMAIN[$i]}" "${T_UPSTREAM[$i]}" "${T_TINYAUTH[$i]}" \
|
||||||
|
>> "$TMPCSV"
|
||||||
|
done
|
||||||
|
|
||||||
|
gum style --foreground "$GREY_LIGHT" --margin "0 2" \
|
||||||
|
" ↑↓ navigate · Enter to view full config · Esc to go back"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
SELECTED=$(gum table \
|
||||||
|
--columns "FILE,DOMAIN,UPSTREAM,TINYAUTH" \
|
||||||
|
--widths "26,30,22,9" \
|
||||||
|
--height 18 \
|
||||||
|
--border.foreground "$ORANGE" \
|
||||||
|
--header.foreground "$ORANGE" \
|
||||||
|
--selected.foreground "$GREY_DARK" \
|
||||||
|
--selected.background "$ORANGE" \
|
||||||
|
< "$TMPCSV" || true)
|
||||||
|
|
||||||
|
rm -f "$TMPCSV"
|
||||||
|
|
||||||
|
[[ -z "$SELECTED" ]] && return
|
||||||
|
|
||||||
|
# Extract filename from first CSV column
|
||||||
|
CHOICE=$(echo "$SELECTED" | cut -d',' -f1 | xargs)
|
||||||
|
|
||||||
|
# ── Show full file contents ────────────────────────────
|
||||||
|
clear
|
||||||
|
gum style \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--bold \
|
||||||
|
--margin "1 2 0 2" \
|
||||||
|
" ▸ ${CHOICE}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
CONTENT=$(ssh_run "cat ${SITES_DIR}/${CHOICE}" 2>/dev/null || true)
|
||||||
|
[[ -z "$CONTENT" ]] && CONTENT="(unable to read file)"
|
||||||
|
|
||||||
|
gum style \
|
||||||
|
--foreground "$WHITE" \
|
||||||
|
--border normal \
|
||||||
|
--border-foreground "$GREY_MID" \
|
||||||
|
--padding "1 2" \
|
||||||
|
--margin "0 2" \
|
||||||
|
"$CONTENT"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
press_enter
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Option 3 – Delete a config ────────────────────────────────
|
||||||
|
|
||||||
|
delete_config() {
|
||||||
|
draw_title
|
||||||
|
gum style \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--bold \
|
||||||
|
--margin "0 2" \
|
||||||
|
" DELETE SITE CONFIG"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Fetch file list
|
||||||
|
mapfile -t FILES < <(ssh_run "ls ${SITES_DIR}/" 2>/dev/null | sort)
|
||||||
|
|
||||||
|
if [[ ${#FILES[@]} -eq 0 ]]; then
|
||||||
|
gum style --foreground "$GREY_LIGHT" --margin "0 2" " No config files found in ${SITES_DIR}/"
|
||||||
|
press_enter
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
CHOICE=$(printf '%s\n' "${FILES[@]}" "── Cancel ──" | \
|
||||||
|
gum choose \
|
||||||
|
--cursor "▶ " \
|
||||||
|
--cursor.foreground "$ORANGE" \
|
||||||
|
--selected.foreground "red" \
|
||||||
|
--header " Select a config to delete:" \
|
||||||
|
--header.foreground "$GREY_LIGHT" \
|
||||||
|
--height 15)
|
||||||
|
|
||||||
|
[[ "$CHOICE" == "── Cancel ──" || -z "$CHOICE" ]] && { gum style --foreground "$GREY_LIGHT" " Cancelled."; press_enter; return; }
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show contents before confirming
|
||||||
|
CONTENT=$(ssh_run "cat ${SITES_DIR}/${CHOICE}" 2>/dev/null || echo "(unable to read file)")
|
||||||
|
gum style \
|
||||||
|
--foreground "$GREY_LIGHT" \
|
||||||
|
--border normal \
|
||||||
|
--border-foreground "red" \
|
||||||
|
--padding "1 2" \
|
||||||
|
--margin "0 2" \
|
||||||
|
"$CONTENT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
gum confirm \
|
||||||
|
--prompt.foreground "$ORANGE" \
|
||||||
|
--selected.background "$ORANGE" \
|
||||||
|
--selected.foreground "$GREY_DARK" \
|
||||||
|
" Permanently delete ${CHOICE} and reload Caddy?" \
|
||||||
|
|| { gum style --foreground "$GREY_LIGHT" " Cancelled."; press_enter; return; }
|
||||||
|
|
||||||
|
ssh_run "rm -f ${SITES_DIR}/${CHOICE}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
gum style --foreground "green" " ✔ Deleted ${SITES_DIR}/${CHOICE}"
|
||||||
|
|
||||||
|
reload_caddy && gum style --foreground "green" " ✔ Caddy reloaded successfully." \
|
||||||
|
|| gum style --foreground "red" " ✗ Caddy reload failed – check logs."
|
||||||
|
press_enter
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Main menu loop ────────────────────────────────────────────
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
draw_title
|
||||||
|
|
||||||
|
MENU_CHOICE=$(gum choose \
|
||||||
|
--cursor "▶ " \
|
||||||
|
--cursor.foreground "$ORANGE" \
|
||||||
|
--selected.foreground "$ORANGE" \
|
||||||
|
--header " What would you like to do?" \
|
||||||
|
--header.foreground "$GREY_LIGHT" \
|
||||||
|
--height 6 \
|
||||||
|
" 1 Add a new site config" \
|
||||||
|
" 2 List / view site configs" \
|
||||||
|
" 3 Delete a site config" \
|
||||||
|
" ✕ Exit")
|
||||||
|
|
||||||
|
case "$MENU_CHOICE" in
|
||||||
|
*"1"*) add_config ;;
|
||||||
|
*"2"*) list_configs ;;
|
||||||
|
*"3"*) delete_config ;;
|
||||||
|
*"✕"*|"") clear; exit 0 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
Executable
+173
@@ -0,0 +1,173 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# --- Theme Configuration (Orange & Grey) ---
|
||||||
|
ORANGE="#FF6B00"
|
||||||
|
GREY_LIGHT="#B3B3B3"
|
||||||
|
GREY_DARK="#2E2E2E"
|
||||||
|
|
||||||
|
export GUM_CHOOSE_CURSOR_FOREGROUND="$ORANGE"
|
||||||
|
export GUM_CHOOSE_SELECTED_FOREGROUND="$ORANGE"
|
||||||
|
export GUM_CHOOSE_ITEM_FOREGROUND="$GREY_LIGHT"
|
||||||
|
export GUM_CONFIRM_SELECTED_BACKGROUND="$ORANGE"
|
||||||
|
export GUM_CONFIRM_SELECTED_FOREGROUND="#000000"
|
||||||
|
export GUM_CONFIRM_UNSELECTED_BACKGROUND="$GREY_DARK"
|
||||||
|
export GUM_CONFIRM_UNSELECTED_FOREGROUND="$GREY_LIGHT"
|
||||||
|
|
||||||
|
# Create a clean temporary log to trap underlying command errors
|
||||||
|
ERROR_LOG=$(mktemp /tmp/chd_converter_err.XXXXXX)
|
||||||
|
trap 'rm -f "$ERROR_LOG"' EXIT
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
clear
|
||||||
|
|
||||||
|
# Title Box Header
|
||||||
|
gum style \
|
||||||
|
--border double \
|
||||||
|
--border-foreground "$ORANGE" \
|
||||||
|
--foreground "$ORANGE" \
|
||||||
|
--margin "1 2" \
|
||||||
|
--padding "1 4" \
|
||||||
|
--align center \
|
||||||
|
--width 40 \
|
||||||
|
"CHD ROM Converter"
|
||||||
|
|
||||||
|
# Main Menu Selection
|
||||||
|
CHOICE=$(gum choose --header="Select an action:" "Compress to CHD" "Extract CHD back to ROM" "Exit")
|
||||||
|
|
||||||
|
case "$CHOICE" in
|
||||||
|
"Compress to CHD")
|
||||||
|
gum style --foreground "$ORANGE" "Select the folder containing ROMs to compress:"
|
||||||
|
TARGET_DIR=$(gum file --directory)
|
||||||
|
|
||||||
|
[ -z "$TARGET_DIR" ] && continue
|
||||||
|
cd "$TARGET_DIR" || continue
|
||||||
|
|
||||||
|
shopt -s nullglob nocaseglob
|
||||||
|
FILES=(*.iso *.cue *.gdi)
|
||||||
|
|
||||||
|
if [ ${#FILES[@]} -eq 0 ]; then
|
||||||
|
gum style --foreground "$GREY_LIGHT" "No compatible files (.iso, .cue, .gdi) found in this folder."
|
||||||
|
gum input --placeholder "Press Enter to return to menu..." --timeout 5s >/dev/null
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONVERTED_ORIGINALS=()
|
||||||
|
FAILED_FILES=()
|
||||||
|
|
||||||
|
for FILE in "${FILES[@]}"; do
|
||||||
|
[ -f "$FILE" ] || continue
|
||||||
|
OUTPUT_CHD="${FILE%.*}.chd"
|
||||||
|
|
||||||
|
# Wrapped inside bash -c so 'gum spin' output stays visible on the terminal screen
|
||||||
|
gum spin --spinner dot --spinner.foreground "$ORANGE" --title.foreground "$GREY_LIGHT" --title "Compressing: $FILE..." -- bash -c "chdman createcd -i '$FILE' -o '$OUTPUT_CHD' >/dev/null 2>'$ERROR_LOG'"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
CONVERTED_ORIGINALS+=("$FILE")
|
||||||
|
|
||||||
|
# Track associated .bin files from inside the .cue file for safe cleanup
|
||||||
|
if [[ "$FILE" =~ \.cue$ ]]; then
|
||||||
|
while IFS= read -r BIN_FILE; do
|
||||||
|
BIN_FILE=$(echo "$BIN_FILE" | tr -d '\r"' | xargs)
|
||||||
|
if [ -f "$BIN_FILE" ]; then
|
||||||
|
CONVERTED_ORIGINALS+=("$BIN_FILE")
|
||||||
|
fi
|
||||||
|
done < <(grep -i 'FILE' "$FILE" | awk -F '"' '{print $2}')
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
FAILED_FILES+=("$FILE")
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if grep -qE "not found|command not found" "$ERROR_LOG" 2>/dev/null; then
|
||||||
|
gum style --foreground "#FF3333" --border normal --border-foreground "#FF3333" --padding "0 1" "Error: 'chdman' is not installed or not in your PATH."
|
||||||
|
gum input --placeholder "Press Enter to return to menu..." >/dev/null
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
gum style --foreground "#FF3333" "Failed to compress: $FILE"
|
||||||
|
gum style --foreground "$GREY_LIGHT" "Reason: $(cat "$ERROR_LOG")"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${#CONVERTED_ORIGINALS[@]} -gt 0 ]; then
|
||||||
|
if gum confirm "Compression complete! Do you want to delete the original source files?"; then
|
||||||
|
for ORIG in "${CONVERTED_ORIGINALS[@]}"; do
|
||||||
|
rm -f "$ORIG"
|
||||||
|
done
|
||||||
|
gum style --foreground "$ORANGE" "Original files cleaned up successfully."
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
elif [ ${#FAILED_FILES[@]} -gt 0 ]; then
|
||||||
|
gum style --foreground "$GREY_LIGHT" "File processing halted due to errors shown above."
|
||||||
|
gum input --placeholder "Press Enter to return to menu..." >/dev/null
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
"Extract CHD back to ROM")
|
||||||
|
gum style --foreground "$ORANGE" "Select the folder containing CHDs to extract:"
|
||||||
|
TARGET_DIR=$(gum file --directory)
|
||||||
|
|
||||||
|
[ -z "$TARGET_DIR" ] && continue
|
||||||
|
cd "$TARGET_DIR" || continue
|
||||||
|
|
||||||
|
shopt -s nullglob nocaseglob
|
||||||
|
FILES=(*.chd)
|
||||||
|
|
||||||
|
if [ ${#FILES[@]} -eq 0 ]; then
|
||||||
|
gum style --foreground "$GREY_LIGHT" "No .chd files found in this folder."
|
||||||
|
gum input --placeholder "Press Enter to return to menu..." --timeout 5s >/dev/null
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
CONVERTED_CHDS=()
|
||||||
|
|
||||||
|
for FILE in "${FILES[@]}"; do
|
||||||
|
[ -f "$FILE" ] || continue
|
||||||
|
BASE_NAME="${FILE%.*}"
|
||||||
|
|
||||||
|
# Check metadata to safely differentiate between multi-track CD structures and flat DVDs
|
||||||
|
if chdman info -i "$FILE" 2>/dev/null | grep -qi "track"; then
|
||||||
|
# CD Mode (.cue + .bin output alignment)
|
||||||
|
OUTPUT_FILE="$BASE_NAME.cue"
|
||||||
|
gum spin --spinner dot --spinner.foreground "$ORANGE" --title.foreground "$GREY_LIGHT" --title "Extracting CD ROM Layout ($BASE_NAME.cue)..." -- bash -c "chdman extractcd -i '$FILE' -o '$OUTPUT_FILE' >/dev/null 2>'$ERROR_LOG'"
|
||||||
|
else
|
||||||
|
# DVD Mode (True standalone single .iso target extraction)
|
||||||
|
OUTPUT_FILE="$BASE_NAME.iso"
|
||||||
|
gum spin --spinner dot --spinner.foreground "$ORANGE" --title.foreground "$GREY_LIGHT" --title "Extracting DVD Image ($BASE_NAME.iso)..." -- bash -c "chdman extractdvd -i '$FILE' -o '$OUTPUT_FILE' >/dev/null 2>'$ERROR_LOG'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
CONVERTED_CHDS+=("$FILE")
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
if grep -qE "not found|command not found" "$ERROR_LOG" 2>/dev/null; then
|
||||||
|
gum style --foreground "#FF3333" "Error: 'chdman' command not found."
|
||||||
|
gum input --placeholder "Press Enter to return to menu..." >/dev/null
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
gum style --foreground "#FF3333" "Failed to extract: $FILE"
|
||||||
|
gum style --foreground "$GREY_LIGHT" "Reason: $(cat "$ERROR_LOG")"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${#CONVERTED_CHDS[@]} -gt 0 ]; then
|
||||||
|
if gum confirm "Extraction complete! Do you want to delete the original CHD files?"; then
|
||||||
|
for CHD in "${CONVERTED_CHDS[@]}"; do
|
||||||
|
rm -f "$CHD"
|
||||||
|
done
|
||||||
|
gum style --foreground "$ORANGE" "Original CHD files cleaned up successfully."
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
gum style --foreground "$GREY_LIGHT" "Extraction failed or was aborted."
|
||||||
|
gum input --placeholder "Press Enter to return to menu..." >/dev/null
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
"Exit")
|
||||||
|
clear
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
+7
-7
@@ -3,7 +3,7 @@
|
|||||||
# ==========================================
|
# ==========================================
|
||||||
# CONFIGURATION (Edit these!)
|
# CONFIGURATION (Edit these!)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
GOTIFY_TOKEN="AH5NXt3g0lSCyfT" # <--- Paste your token here
|
GOTIFY_TOKEN= # <--- Paste your token here
|
||||||
GOTIFY_URL="https://gotify.marlow.quest"
|
GOTIFY_URL="https://gotify.marlow.quest"
|
||||||
SRC_DIR="$HOME/Videos/Compress"
|
SRC_DIR="$HOME/Videos/Compress"
|
||||||
OUT_DIR="$SRC_DIR/Complete"
|
OUT_DIR="$SRC_DIR/Complete"
|
||||||
@@ -80,20 +80,20 @@ for f in "${files[@]}"; do
|
|||||||
# Spinner & Handbrake
|
# Spinner & Handbrake
|
||||||
gum spin --spinner minidot --spinner.foreground 208 --title "Encoding: $filename ($old_mb MB)..." -- \
|
gum spin --spinner minidot --spinner.foreground 208 --title "Encoding: $filename ($old_mb MB)..." -- \
|
||||||
bash -c 'HandBrakeCLI -i "$IN_FILE" -o "$OUT_FILE" -e svt_av1 --encoder-preset 8 -q "$QUALITY" --vfr -l 1080 -E opus -B 128 > /dev/null 2>&1'
|
bash -c 'HandBrakeCLI -i "$IN_FILE" -o "$OUT_FILE" -e svt_av1 --encoder-preset 8 -q "$QUALITY" --vfr -l 1080 -E opus -B 128 > /dev/null 2>&1'
|
||||||
|
|
||||||
if [ $? -eq 0 ] && [ -f "$OUT_FILE" ]; then
|
if [ $? -eq 0 ] && [ -f "$OUT_FILE" ]; then
|
||||||
new_size=$(wc -c < "$OUT_FILE")
|
new_size=$(wc -c < "$OUT_FILE")
|
||||||
new_mb=$(awk "BEGIN {printf \"%.1f\", $new_size/1048576}")
|
new_mb=$(awk "BEGIN {printf \"%.1f\", $new_size/1048576}")
|
||||||
saved_mb=$(awk "BEGIN {printf \"%.1f\", $old_mb - $new_mb}")
|
saved_mb=$(awk "BEGIN {printf \"%.1f\", $old_mb - $new_mb}")
|
||||||
|
|
||||||
gum style --foreground 76 "✓ $filename"
|
gum style --foreground 76 "✓ $filename"
|
||||||
gum style --foreground 245 " ↳ Size: ${old_mb}MB → ${new_mb}MB (Saved: ${saved_mb}MB)"
|
gum style --foreground 245 " ↳ Size: ${old_mb}MB → ${new_mb}MB (Saved: ${saved_mb}MB)"
|
||||||
|
|
||||||
TOTAL_OLD_BYTES=$((TOTAL_OLD_BYTES + old_size))
|
TOTAL_OLD_BYTES=$((TOTAL_OLD_BYTES + old_size))
|
||||||
TOTAL_NEW_BYTES=$((TOTAL_NEW_BYTES + new_size))
|
TOTAL_NEW_BYTES=$((TOTAL_NEW_BYTES + new_size))
|
||||||
((FILE_COUNT++))
|
((FILE_COUNT++))
|
||||||
else
|
else
|
||||||
gum style --foreground 196 "✗ Failed: $filename"
|
gum style --foreground 196 "✗ Failed: $filename"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
@@ -110,11 +110,11 @@ gum style \
|
|||||||
|
|
||||||
if [ "$GOTIFY_ENABLED" = true ] && [ $FILE_COUNT -gt 0 ]; then
|
if [ "$GOTIFY_ENABLED" = true ] && [ $FILE_COUNT -gt 0 ]; then
|
||||||
MESSAGE="Finished processing $FILE_COUNT videos. Total space saved: $TOTAL_SAVED_MB MB."
|
MESSAGE="Finished processing $FILE_COUNT videos. Total space saved: $TOTAL_SAVED_MB MB."
|
||||||
|
|
||||||
curl -s -S "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \
|
curl -s -S "$GOTIFY_URL/message?token=$GOTIFY_TOKEN" \
|
||||||
-F "title=✅ Video Encoding Complete" \
|
-F "title=✅ Video Encoding Complete" \
|
||||||
-F "message=$MESSAGE" \
|
-F "message=$MESSAGE" \
|
||||||
-F "priority=5" > /dev/null
|
-F "priority=5" > /dev/null
|
||||||
|
|
||||||
gum style --foreground 240 " (Gotify notification sent)"
|
gum style --foreground 240 " (Gotify notification sent)"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user