#!/bin/bash
#  wpm.sh - Wireguard (VPN) Peer Manager (zenity-based GUI)
# ========================================================
#  Setup for Debian-based Linux distros:
#   0) install zenity, wireguard & openresolv apt packages
#   1) create several ProtonVPN wireguard peer profiles[1]
#   2) download profiles & place in /etc/wireguard/
#   3) run 'sudo chmod 705 /etc/wireguard'
#   4) run 'sudo chmod 600 /etc/wireguard/*.conf'
#   5) copy script to ~/bin & run 'chmod 700 ~/bin/wvpm.sh'
#   6) optionally create menu entry for Desktop Environment
#
#  [1] wg-quick(8): "MY_WG_PEER_NAME" must be unique and
#      limited to 15 charaters in length; doesn't include
#      the ".conf" extension.
# ========================================================
# :adjust these as needed:
# location of wireguard peer config files:
WG_PEERS="/etc/wireguard/*.conf"
#
# ssh/sudo GUI password prompter:
export SUDO_ASKPASS=/usr/libexec/seahorse/ssh-askpass
#
# Width & Height of Zenity Window:
WZW=200
HZW=400
# ========================================================
# !!!!!!!! leave everything below this line alone !!!!!!!!
# ========================================================

# gather peer names into PEERS var:
for I in $WG_PEERS ;do
  PEERS+="$(basename $I .conf) "
done

# tests if peer is enabled:
if_enabled() {
  if [[ "$(systemctl is-enabled wg-quick@"$1")" == enabled ]]
        then
    return 0
  else
    return 1
  fi
}

# tests if peer is active:
if_active() {
  if [[ "$(systemctl is-active wg-quick@"$1")" == active ]]
        then
    return 0
  else
    return 1
  fi
}

# set radio button TRUE if peer is UP:
button_state() {
  if ( if_active "$1" ) ;then
    echo 'TRUE'
  else
    echo 'FALSE'
  fi
}

# report if peer is ENABLED/DISABLED at system startup:
startup_state() {
  if ( if_enabled "$1" ) ;then
    echo '√'
  else
    echo '-'
  fi
}

# generate peer listing for zenity menu:
peer_list() {
  for PEER in $PEERS ;do
    echo "$(button_state $PEER)" "$PEER" "$(startup_state $PEER)"
  done
}

# shutdown ALL peers:
all_down() {
  for PEER in $PEERS ;do
    ( if_active "$PEER" ) && sudo -AE systemctl stop wg-quick@"$PEER"
  done
}

# enable||disable *active* peer at startup:
active_peer_toggle() {
  for PEER in $PEERS ;do
    if ( if_active "$PEER" ) ;then
      if ( if_enabled "$PEER" ) ;then
                    sudo -AE systemctl disable wg-quick@"$PEER"
      else
                    sudo -AE systemctl enable wg-quick@"$PEER"
      fi
    else
      sudo -AE systemctl disable wg-quick@"$PEER"
    fi
  done
}

# toggle peer (ARG1) to UP:
peer_up() {
  all_down
  sudo -AE systemctl start wg-quick@"$1"
}

# zenity window header text (here-doc; uses Pango markup):
zen_head() {
cat <<EOF
<tt> VPN service: \
<span foreground="magenta" size="large">Proton</span>\
<span foreground="lightblue" size="large">VPN</span>
<span foreground="white">
 Select a peer and click <b>ON</b> to switch.
 <b>OFF</b> shuts down <i>ALL</i> peers.

 <b>√</b> => enabled at boot-up; click <b>@BOOT</b> to
 toggle. Selected peer <i>must</i> be active.
</span></tt>
EOF
}

# pick a peer or shut all down:
pick_peer() {
  zenity --title='Wireguard Peer Manager' --width=$WZW --height=$HZW \
         --list --radiolist --column='State  ' --column='Wireguard Peers    ' \
         --column='enabled @ boot' --print-column=2 --text="$(zen_head)" \
         --ok-label=ON --extra-button=OFF --extra-button=@BOOT --cancel-label=Quit \
  $(peer_list)
}

# conditional action based on return value of pick_peer():
set_state() {
  case "$1" in
      '') exit 1 ;;
     OFF) all_down ;;
   @BOOT) active_peer_toggle ;;
       *) peer_up $1 ;;
  esac
}

# main - loops until set_state exit 1 (false):
main() {
  while : ;do
    set_state "$(pick_peer)"
    sleep 1
  done
}
main &
