#!/bin/bash

# only run as root
if [[ $EUID -gt 0 ]]; then
  echo "Please run as root"
  exit
fi
#######################################################################################
#########                                                                      ########
########                         PARSE PARAMS                                ##########
#######                                                                     ###########
#######################################################################################

POSITIONAL_ARGS=()

while [[ $# -gt 0 ]]; do
  case $1 in
    -c|--cert-type)
      CERT_TYPE="$2"
      shift # past argument
      shift # past value
      ;;
    -d|--debug)
      DEBUG="$2"
      shift # past argument
      shift # past value
      ;;
    -*|--*)
      echo "Unknown option $1"
      exit 1
      ;;
    *)
      POSITIONAL_ARGS+=("$1") # save positional arg
      shift # past argument
      ;;
  esac
done

set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
# script fails on error
set -e

if [ "$DEBUG" == "true" ]; then
    set -x
fi

#######################################################################################
#########                                                                      ########
########                       SETUP FUNCTIONS                               ##########
#######                                                                     ###########
#######################################################################################

declare process_echo_history
declare last_process_status
spinner() {
set +x
  #spinner animation
  local pid=$!
  local delay=0.20
  local spinstr='|/-\'
  while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
    local temp=${spinstr#?}
    printf " [%c]  " "$spinstr"
    local spinstr=$temp${spinstr%"$temp"}
    sleep $delay
    printf "\b\b\b\b\b\b"
  done
  wait $pid
  last_process_status=$?
  printf "    \b\b\b\b"
  if [[ $DEBUG == "true" ]]; then
  set -x
  fi
}

process_echo() {
if [[ $DEBUG == "true" ]]; then
    echo "$@ "
    spinner
else
  local RED=$(tput setaf 1)
  local GREEN=$(tput setaf 2)
  local YELLOW=$(tput setaf 3)
  local ENDCOLOR=$(tput sgr0)
  local text="$1"
  local text_color=${!2:-$(tput sgr0)}
  local characters=${#text}
  local start_col=$(($(tput cols) / 2 - $characters / 2))
  local start_line=$(($(tput lines) / 2))
  local spinner_col=$(($(tput cols) - 7))
  tput civis
  clear
  echo -e "$process_echo_history"

  tput cup $start_line $start_col
  tput el
  echo -en "${text_color}$text${ENDCOLOR}"

  tput cup $start_line $spinner_col

  spinner
  p_status=$([ "$last_process_status" -eq 0 ] && echo "${GREEN}[DONE]${ENDCOLOR}" || echo "${RED}[FAIL]${ENDCOLOR}")
  echo -e "${GREEN}${p_status}${ENDCOLOR}"
  process_echo_history+="\n $text ${p_status}"
  sleep 0.5
  tput clear
  echo -e "$process_echo_history $ENDCOLOR"
  sleep 0.2
  tput cvvis
  tput cnorm
fi
}

# install dependencies function
dep_install() {
  apt install -y software-properties-common
  add-apt-repository ppa:deadsnakes/ppa
  apt update -y
  apt install -y dialog dropbear squid stunnel cmake make wget gcc build-essential nodejs acl unzip zip tmux socat python3.10 python3.10-venv vnstat
}

# function to enable and start vnstat service
vnstat_setup() {
  systemctl enable --now vnstat.service
  systemctl restart vnstat.service
}


# build and install function
build_install_badvpn() {
  # add-apt-repository ppa:ambrop7/badvpn && apt-get update -y && apt-get install badvpn -y # todo: test this installation method
  wget https://github.com/ambrop72/badvpn/archive/master.zip && unzip master.zip && rm master.zip
  mkdir -p badvpn-master/build
  cd badvpn-master/build
  cmake .. -DBUILD_NOTHING_BY_DEFAULT=1 -DBUILD_UDPGW=1 && make install
}

# zerossl setup function
zerossl_setup() {
  mkdir ../../certs
  cd ../../certs
  local certs_dir=${PWD}

  TERMINAL=$(tty)
  HEIGHT=15
  WIDTH=40
  CHOICE_HEIGHT=4
  BACKTITLE="Coded by @BlurryFlurry & @noobconner21"
  TITLE="Zerossl setup"
  MENU="Choose one of the following methods for zerossl setup:"

  OPTIONS=(1 "Manually upload zerossl zip file to $(pwd) directory"
  2 "Provide a direct remote download link to fetch the zerossl certificate zip file"
  3 "acme.sh easy automation")

  CHOICE=$(dialog --clear --nocancel \
    --backtitle "$BACKTITLE" \
    --title "$TITLE" \
    --menu "$MENU" \
    $HEIGHT $WIDTH $CHOICE_HEIGHT \
    "${OPTIONS[@]}" \
    2>&1 >"$TERMINAL")

  clear
  case $CHOICE in
  1)
    echo "Manually upload zerossl zip file to $(pwd) directory"
    # zerossl cert files steps for manually upload
    clear
    echo -e " Step 1: visit https://zerossl.com, \n Step 2: login, \n Step 3: verify domain and download certificate files, \n Step 4: upload the zip file to $(pwd)/ directory \n"
    echo .
    read -r -s -p $'Press ESCAPE to continue...\n' -d $'\e'
    until [ "$(ls ./*.zip)" ]; do
      read -r -s -p $'Certs directory is still empty, Please upload files and press ESCAPE to continue...\n' -d $'\e'
    done

    ;;
  2)
    echo "Provide a direct remote download link to fetch the zerossl certificate zip file"
    read -p "What's your zerossl zip file link? (Dropbox): " zerofileslink
    until [ "$(curl -o /dev/null --silent --head --write-out '%{http_code}' "$zerofileslink" 2>/dev/null)" -eq 200 ]; do
      read -p $'\e[31mPlease provide a valid download url to your zerossl zip file (Dropbox)\e[0m: ' zerofileslink
    done
    wget "$zerofileslink"

    until [ "$(ls ./*.zip)" ]; do
      read -r -s -p $'\e[31m Certs directory is still empty, Please upload files and press ESCAPE to continue...\e[0m \n' -d $'\e'
    done
    ;;
  3)
    echo -e "acme.sh standalone webserver (Beta)\n\n"
    read -p "Please provide a valid email address: " zerossl_email
    read -p "Please provide the domain name: " zerossl_domain

    systemctl stop nodews1 2>&1 >/dev/null
    process_echo "Disabling nodews1 proxy script to clear the port 80 temporary"
    #              curl https://get.acme.sh | sh -s email="$zerossl_email" --issue -d "$zerossl_domain" --standalone --server letsencrypt --staging --test
    #              cat ~/.acme.sh/"$zerossl_domain"/"$zerossl_domain".key ~/.acme.sh/"$zerossl_domain"/"$zerossl_domain" ~/.acme.sh/"$zerossl_domain"/fullchain.cer >/etc/stunnel/stunnel.pem

    curl https://get.acme.sh | sh -s email="$zerossl_email" >/dev/null 2>&1 &
    process_echo "Installing acme.sh..."
    bash ~/.acme.sh/acme.sh --register-account -m "$zerossl_email" >/dev/null 2>&1 &
    process_echo "Registering zerossl account..."
    #    bash ~/.acme.sh/acme.sh --issue --standalone -d "$zerossl_domain" --force --staging --test >/dev/null 2>&1 &
    if [[  $CERT_TYPE == "staging"  ]]; then
          bash ~/.acme.sh/acme.sh --issue --standalone -d "$zerossl_domain" --force --staging --test >/dev/null 2>&1 &
          process_echo "Issuing staging certificates..."
    else
              bash ~/.acme.sh/acme.sh --issue --standalone -d "$zerossl_domain" --force >/dev/null 2>&1 &
              process_echo "issuing standalone certificates..."
    fi
    bash ~/.acme.sh/acme.sh --installcert -d "$zerossl_domain" --fullchainpath "$certs_dir"/bundle.cer --keypath "$certs_dir"/private.key >/dev/null 2>&1 &
    process_echo "Installing certificates..."
    cat "$certs_dir"/private.key "$certs_dir"/bundle.cer >/etc/stunnel/stunnel.pem
    chmod 400 /etc/stunnel/stunnel.pem

    systemctl start nodews1 2>&1 >/dev/null
    process_echo "Starting service nodews1 proxy script back online"
    ;;
  esac
  # unzip certs, create stunnel.pem, start stunnel service
  if [ ! -f "/etc/stunnel/stunnel.pem" ]; then
    unzip ./*.zip
    cat private.key certificate.crt ca_bundle.crt >/etc/stunnel/stunnel.pem
    chmod 400 >/etc/stunnel/stunnel.pem
  fi
  systemctl start stunnel4
  systemctl enable stunnel4
}

telegram_bot_setup() {
  read -p "Enter a username for the Telegram bot service (default is 'ptb'): " username
  username=${username:-ptb}          # use 'ptb' as default username if none was provided
  useradd -m -s /bin/false "$username" # create a new Linux user with the specified username
  cd /home/"$username"
  git clone https://github.com/BlurryFlurry/tg-vps-manager.git bot >/dev/null 2>&1 &
  process_echo "Cloning repository to /home/$username/bot ..." YELLOW
  cd bot

  /usr/bin/env python3.10 -m venv venv
  source venv/bin/activate
  pip3.10 install --upgrade pip  >/dev/null 2>&1 &
  process_echo "Upgrading pip3.10" YELLOW
  pip3.10 install wheel >/dev/null 2>&1 &
  process_echo "Installing wheel" YELLOW
  pip3.10 install -r requirements.txt >/dev/null 2>&1 &
  process_echo "Installing requirements..." YELLOW
  deactivate
  sudo chown -R "$username":"$username" /home/"$username"
  systemctl link /home/"$username"/bot/ptb@.service
  echo "Use https://t.me/BotFather to create a new telegram bot for your vps manager"
  echo "Copy the bot token and paste it here"
  read -p "Telegram Bot token: " bot_token
  echo "Use https://t.me/raw_data_bot to find your Telegram ID and paste it here"
  echo "This telegram user ID will be the only user ID that have /grant command permission"
  echo "(you can change these values by editing the env_vars file)"
  read -p "Admin telegram ID: " admin_id
  echo "grant_perm_id=$admin_id" >env_vars
  echo "telegram_bot_token=$bot_token" >>env_vars
  
  mkdir -p "$HOME"/.config
  echo "$username" >"$HOME/.config/ptb-service-user"
  
  systemctl daemon-reload # reload systemd configuration
  curl -sSL https://raw.githubusercontent.com/BlurryFlurry/dig-my-tunnel/main/perm_fixer.sh | sh -s -- $username
  
  systemctl start ptb@"$username".service && echo "Telegram bot service has started!"
  systemctl enable ptb@"$username".service 2>&1
  
}



#######################################################################################
#########                                                                      ########
########                       INSTALL PROCESS                               ##########
#######                                                                     ###########
#######################################################################################

ufw disable || echo "ufw is not found. Continuing.."

# install updates

apt update -qq -y >/dev/null 2>&1 &
process_echo "Updating packages..." YELLOW
apt upgrade -qq -y >/dev/null 2>&1 &
process_echo "Upgrading..." YELLOW

# install dependencies
dep_install >/dev/null 2>&1 &
process_echo "Installing dependencies..." YELLOW

# build and install badvpn
build_install_badvpn >/dev/null 2>&1 &
process_echo "Building and installing badvpn..." YELLOW

# dropbear config
sed -i 's/NO_START=1/NO_START=0/' /etc/default/dropbear
sed -i 's/DROPBEAR_PORT=22/DROPBEAR_PORT=40000/' /etc/default/dropbear

# set banner
read -p "Set custom banner?[Y/n]" -n 1 -r

if [[ $REPLY =~ ^[Yy]$ ]]; then
  sed -i 's|DROPBEAR_BANNER=""|DROPBEAR_BANNER="/etc/dropbear/banner.dat"|' /etc/default/dropbear
  clear
  echo "Paste your banner and then type EOF (in uppercase) and hit ENTER"
  while read line; do
    [[ "$line" == "EOF" ]] && break
    echo "$line" >>"/etc/dropbear/banner.dat"
  done
fi

# systemd unit file node javascript proxy
wget -P /etc/systemd/system/ https://cdn.jsdelivr.net/gh/BlurryFlurry/dig-my-tunnel@main/nodews1.service >/dev/null 2>&1 &
process_echo "Downloading systemd unit file of nodejs proxy..." YELLOW
mkdir /etc/p7common

# proxy script
wget -P /etc/p7common https://gitlab.com/PANCHO7532/scripts-and-random-code/-/raw/master/nfree/proxy3.js >/dev/null 2>&1 &
process_echo "Downloading nodejs proxy script..." YELLOW

# enable startup and run service
systemctl enable --now nodews1.service >/dev/null 2>&1 &
process_echo "Enabling and starting the service..." YELLOW

# stunnel config listens on port 443
wget -P /etc/stunnel/ https://cdn.jsdelivr.net/gh/BlurryFlurry/dig-my-tunnel@main/stunnel.conf >/dev/null 2>&1 &
process_echo "Configuring stunnel..." YELLOW

zerossl_setup

# badvpn systemd service unit file, and start the service

wget -P /etc/systemd/system/ https://cdn.jsdelivr.net/gh/BlurryFlurry/dig-my-tunnel@main/badvpn.service >/dev/null 2>&1 &
process_echo "Downloading badvpn systemd service unit file..." YELLOW

systemctl enable --now badvpn >/dev/null 2>&1 &
process_echo "starting badvpn unit file..." YELLOW

vnstat_setup >/dev/null 2>&1 &
process_echo "Configuring vnstat..." YELLOW


echo "Configuring security settings.."
# pam service disable enforce_for_root option if exists
sed -i 's/enforce_for_root//' /etc/pam.d/common-password

# add fake shell paths to prevent interractive shell login
echo '/bin/false' >>/etc/shells
echo '/usr/sbin/nologin' >>/etc/shells
echo "Done."
sleep 1
clear

telegram_bot_setup

# create user
read -p "Create a user?[N/y]" -n 1 -r

if [[ $REPLY =~ ^[Yy]$ ]]; then
  echo ""
  read -p "Enter username (characters): " ssh_user
  until [[ "$ssh_user" =~ ^[0-9a-zA-Z]{2,8}$ ]]; do
    read -p $'\e[31mPlease enter a valid username\e[0m: ' ssh_user
  done

  useradd -M "$ssh_user" -s /bin/false && echo "$ssh_user user has successfully created."
  set +e
  until passwd $ssh_user; do
    echo "Try again"
    sleep 1
  done
  read -p "Max logins limit: " maxlogins
  echo "$ssh_user  hard  maxlogins ${maxlogins}" >/etc/security/limits.d/"$ssh_user".conf
fi


echo "GET / HTTP/1.1[crlf]Host: [host][crlf]Connection: upgrade [crlf] Upgrade: websocket[crlf][crlf]"

read -rp "Press <Enter> to restart the server"
reboot