#!/bin/bash

#
# Name:         seedbox-cp
# Version:      1.0.92
# Description:  Seedbox Control Panel
#
# (c) 2017-2024, Rapidseedbox, alexey@rapidseedbox.com
#

export LANG=en_US

# Fix "bad" terminals
case "${TERM}" in
  "xterm" )
      export TERM="linux"
      ;;
esac


APP_TITLE="Seedbox Control Panel"
SC_NAME="$( basename "${0}" )"
_VER="$( grep -m 1 -E '^#\s*Version:\s+' "${0}" | awk '{print $NF}' )"
LOGFILE="/var/log/seedbox-cp.log"
#DEBUG="yes"
DEBUG="no"

LSB_VENDOR="$( lsb_release -si 2>&1 | awk '{print $1}' )"
LSB_RELEASE="$( lsb_release -sr )"
LSB_CODENAME="$( lsb_release -sc )"
LSB_DESCRIPTION="$( lsb_release -sd | sed -e 's/^\"\(.*\)\"$/\1/')"
case "${LSB_VENDOR}" in
  "CentOS"|"CentOSStream"|"Debian")
      LSB_RELEASE="$( echo "${LSB_RELEASE}" | awk -F'.' '{print $1}' )"
      ;;
esac
LSB_VER="${LSB_VENDOR}${LSB_RELEASE}"


# Collect some usage statistics :)
RSB_STATS_DIR="/var/local/stats"
[ ! -d "${RSB_STATS_DIR}" ] && mkdir -p "${RSB_STATS_DIR}"
if [ -e "${RSB_STATS_DIR}/${SC_NAME}.run.cnt" ] ; then
    run_cnt="$( cat "${RSB_STATS_DIR}/${SC_NAME}.run.cnt" )"
    run_cnt="$((run_cnt + 1))"
else
    run_cnt=1
fi
echo "${run_cnt}" > "${RSB_STATS_DIR}/${SC_NAME}.run.cnt"



function usage() {
    if [ "${USE_UI}" = "yes" ] ; then
        [ -n "${ERR_MSG}" ] && echo "ERROR: ${ERR_MSG}"
        cat <<-EOF
	Usage:
	------------
	    ${SC_NAME} [-h] [-u USERNAME] [-d] [-s service [-a command] [-e args] [-f format]]

	    -h       - Display this help message
	    -d       - Turn on DEBUG mode

	Arguments:
	------------
	    USERNAME - default value is 'user'

	    service  - all[:started|stopped,enabled|disabled]

	    service  - apache, ariang, autobrr, autodl, bazarr, btsync, cherrymusic, cloudcmd,
	               cloudtorrent, couchpotato, cuberite, deluged, delugeweb, docker, emby,
	               filebrowser, filecommander, flood, ftpd, jackett, jellyfin, lidarr,
	               madsonic, mysql, nginx, nomachine, nzbget, nzbhydra2, ombi, openvpn, overseer,
	               plex, plexpy, prowlarr, puppeteer, pyload, qbittorrent,
	               radarr, rclonewebui, readarr, resiliosync, rtorrent, sabnzbd, sickbeard,
	               sickchill, sickrage, simpletorrent, softethervpn, sonarr, sonarrlatest,
	               ssh, storm, subsonic, syncthing, tautulli, thinlincweb, transmission,
	               utorrent, vnc, webssh, whisparr, wiztorrent, xrdp, 3proxy

	    NB!      - you can use services list here - comma separated ( f.e.: -s apache,vnc,plex )

	    command  - status | restart | start | stop | enable | disable | monitor | unmonitor | list
	               (Default: status)

	    Commands specific to 'ssh' service:
	    ------------------------------------
	             - root-enable | root-disable | root-key-add -e 'AUTHORIZED-KEY' | root-key-del -e 'AUTHORIZED-KEY'

	    Commands specific to 'plex' service:
	    ------------------------------------
	             - reset | claim

	    NB!      - you can use commands list here - comma separated ( f.e.: -a stop,disable,unmonitor )

	    args     - arguments for a given command
	               f.e.: seedbox-cp -s plex -a claim -e claim-XxXxXxZzYyAaBb
	                     seedbox-cp -s ssh  -a root-key-add -e 'ssh-rsa AAAAB3Nz.....9Q== root@workstation'
	                     seedbox-cp -s ssh  -a root-key-del -e 'ssh-rsa AAAAB3Nz.....9Q== root@workstation'

	    format   - json | xml (Default: json)

	Examples:
	------------
	    Dialog UI:
	        ${SC_NAME}
	        ${SC_NAME} -u username
	    No UI:
	        ${SC_NAME} -u username -s all -a status -f xml
	        ${SC_NAME} -u username -s deluged -a restart -f json
	        ${SC_NAME} -s all -a status -f json | jq . | less
	        ${SC_NAME} -s all -a status -f xml | xmllint -format - | less
	EOF
    else
        case "${FORMAT}" in
          "json")
              cat <<-EOF
		{
		"version":"${_VER}",
		"result":"error",
		"resultmsg":"${ERR_MSG}"
		}
		EOF
              ;;
          "xml")
              cat <<-EOF
		<?xml version="1.0"?>
		<data>
		<version>${_VER}</version>
		<result>error</result>
		<resultmsg>${ERR_MSG}</resultmsg>
		</data>
		EOF
              ;;
        esac
    fi
}

# Quick checks before we allow bad things to happen
_uid="$( id -u )"
if [ ${_uid} -ne 0 ] ; then
    echo -en "ERROR: Sorry\n'root' credentials required to run this script\n"
    exit 1
fi

if [ -z "${BASH_VERSINFO}" ]; then
    echo "ERROR: You must execute this script with 'bash'"
    exit 1
fi

# Default settings
USERNAME="user"
SERVICE="all"
COMMAND="status"
FORMAT="json"
USE_UI="yes"
_STATE_STARTED=""
_STATE_STOPPED=""
_STATE_ENABLED=""
_STATE_DISABLED=""

# Parse command line
OPTIND=1
PARSE_ERR=0
ERR_MSG=""
EXTRA_ARGS=""
while getopts ":u:s:a:e:f:hd" params; do
    case "${params}" in
      u)
          if [[ ${OPTARG} = -* ]] ; then
              [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
              ERR_MSG="${ERR_MSG}Option -${params} requires an argument"
              PARSE_ERR=1
              continue
          fi
          USERNAME="${OPTARG}"
          ;;
      s)
          USE_UI="no"
          if [[ ${OPTARG} = -* ]] ; then
              [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
              ERR_MSG="${ERR_MSG}Option -${params} requires an argument"
              PARSE_ERR=1
              continue
          fi
          SERVICE="$( echo "${OPTARG}" \
                        | awk -F: '{print $1}' \
                        | sed -e 's/,/ /g' \
                        | tr '[:upper:]' '[:lower:]' )"
          SERVICE_STATE="$( echo "${OPTARG}" \
                        | awk -F: '{print $2}' \
                        | sed -e 's/,/ /g' \
                        | tr '[:upper:]' '[:lower:]' )"
          for _svc in ${SERVICE} ; do
              case "${_svc}" in
                  "all"|"apache"|"ariang"|"autobrr"|"autodl"|"bazarr"|"btsync"|"cherrymusic"|"cloudcmd" \
                | "cloudtorrent"|"couchpotato"|"cuberite"|"deluged" \
                | "delugeweb"|"docker"|"emby"|"filebrowser"|"filecommander"|"flood"|"ftpd" \
                | "jackett"|"jellyfin"|"lidarr"|"madsonic"|"mysql"|"nginx"|"nomachine"|"nzbget"|"nzbhydra2" \
                | "ombi"|"openvpn"|"overseerr"|"plex"|"plexpy"|"prowlarr"|"puppeteer"|"pyload" \
                | "qbittorrent"|"radarr" \
                | "rclonewebui"|"readarr"|"resiliosync"|"rtorrent"|"sabnzbd"|"sickbeard"|"sickchill" \
                | "sickrage"|"simpletorrent"|"softethervpn"|"sonarr"|"sonarrlatest" \
                | "ssh"|"storm"|"subsonic"|"syncthing"|"tautulli"|"thinlincweb"|"transmission" \
                | "utorrent"|"vnc"|"webssh"|"whisparr"|"wiztorrent"|"xrdp"|"3proxy" \
                )
                    if [ "${_svc}" = "all" ] ; then
                        SERVICE="all" ; break
                    else
                        continue
		    fi
                    ;;
                *)
                    ERR_MSG="${ERR_MSG}Invalid service name specified: [${_svc}]"
                    PARSE_ERR=1
                    ;;
	      esac
          done
          for _state in ${SERVICE_STATE} ; do
              case "${_state}" in
                "started")
                    _STATE_STARTED="yes"
                    continue ;;
                "stopped")
                    _STATE_STOPPED="yes"
                    continue ;;
                "enabled")
                    _STATE_ENABLED="yes"
                    continue ;;
                "disabled")
                    _STATE_DISABLED="yes"
                    continue ;;
                *)
                    [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
                    ERR_MSG="${ERR_MSG}Invalid service state specified: [${_state}]"
                    PARSE_ERR=1
              esac
          done
          if [ "${_STATE_STARTED}" = "yes" -a "${_STATE_STOPPED}" = "yes" ] ; then
              ERR_MSG="${ERR_MSG}Only one of sevice states should be specified: [started/stopped]"
              PARSE_ERR=1
          fi
          if [ "${_STATE_ENABLED}" = "yes" -a "${_STATE_DISABLED}" = "yes" ] ; then
              ERR_MSG="${ERR_MSG}Only one of sevice states should be specified: [enabled/disabled]"
              PARSE_ERR=1
          fi
          ;;
      a)
          USE_UI="no"
          if [[ ${OPTARG} = -* ]] ; then
              [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
              ERR_MSG="${ERR_MSG}Option -${params} requires an argument"
              PARSE_ERR=1
              continue
          fi
          COMMAND="$( echo "${OPTARG}" \
                        | sed -e 's/,/ /g' \
                        | tr '[:upper:]' '[:lower:]' )"
          for _cmd in ${COMMAND} ; do
              case "${_cmd}" in
                 "status"\
                |"restart"\
                |"start"\
                |"stop"\
                |"enable"\
                |"disable"\
                |"monitor"\
                |"unmonitor"\
                |"list"\
                |"reset"\
                |"claim"\
                |"root-enable"\
                |"root-disable"\
                |"root-key-add"\
                |"root-key-del"\
                 )
                    ;;
                *)
                    [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
                    ERR_MSG="${ERR_MSG}'${_cmd}': Unrecognized command. Only 'status', 'restart', 'start', 'stop', 'enable', 'disable', 'monitor', 'unmonitor', 'list', root-enable (ssh only), root-disable (ssh only), root-key-add (ssh only), root-key-del (ssh only), 'reset' (plex only), 'claim' (plex only) commands supported"
                    PARSE_ERR=1
                    continue
                    ;;
              esac
          done
          ;;
      e)
          USE_UI="no"
          if [[ ${OPTARG} = -* ]] ; then
              [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
              ERR_MSG="${ERR_MSG}Option -${params} requires an argument"
              PARSE_ERR=1
              continue
          fi
          EXTRA_ARGS="${OPTARG}"
          ;;
      f)
          USE_UI="no"
          if [[ ${OPTARG} = -* ]] ; then
              [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
              ERR_MSG="${ERR_MSG}Option -${params} requires an argument"
              PARSE_ERR=1
              continue
          fi
          case "${OPTARG}" in
            "json"|"xml")
                FORMAT="${OPTARG}"
                ;;
            *)
                [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
                ERR_MSG="${ERR_MSG}Only 'json' or 'xml' formats supported"
                PARSE_ERR=1
                continue
          esac
          ;;
      d)
          DEBUG="yes"
          ;;
      h)
          usage ; exit 0
          ;;
      \?) 
          [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
          ERR_MSG="${ERR_MSG}Invalid option: -${OPTARG}"
          PARSE_ERR=1
          ;;
      :)
          [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
          ERR_MSG="${ERR_MSG}Option -${OPTARG} requires an argument"
          PARSE_ERR=1
          ;;
    esac
done
if [ ${PARSE_ERR} -ne 0 ] ; then
    usage ; exit 1
fi
shift "$((OPTIND-1))"

#echo "SERVICE:       [${SERVICE}]"
#echo "SERVICE_STATE: [${SERVICE_STATE}]"
#exit

# Check username
USERUID="$( id -u "${USERNAME}" 2>/dev/null )"
if [ -z "${USERUID}" ] ; then
    [ -n "${ERR_MSG}" ] && ERR_MSG="${ERR_MSG}; "
    ERR_MSG="${ERR_MSG}Sorry. ${USERNAME}: account not found"
    usage
    exit 1
fi

# First regular user's account ID
FIRST_UID="$( grep -e '^UID_MIN\s*' "/etc/login.defs" | awk '{print $2}' )"

# Main return code for the script
retcode=0

# User's home directory
USERHOME="/home/${USERNAME}"


# Define the dialog exit status codes and options
DIALOG_OK=0
DIALOG_CANCEL=1
DIALOG_HELP=2
DIALOG_EXTRA=3
DIALOG_ITEM_HELP=4
DIALOG_ESC=255
#DIALOG_OPTS="--ascii-lines --no-collapse --no-shadow"
#DIALOG_OPTS="--ascii-lines --no-collapse"
DIALOG_OPTS="--ascii-lines --no-collapse --colors --cr-wrap"

if [ "${1}" = "-h" -o "${1}" = "--help" ] ; then
    usage ; exit 0
fi

#
# Some commands are allowed to the specific services only
#
case "${COMMAND}" in
  "root-enable"|"root-disable"|"root-key-add"|"root-key-del")
      if [ "${SERVICE}" != "ssh" ] ; then
          ERR_MSG="${COMMAND}: command is not allowed for service '${SERVICE}'"
          PARSE_ERR=1
      fi
      case "${COMMAND}" in
        "root-key-add"|"root-key-del")
            if [ -z "${EXTRA_ARGS}" ] ; then
                ERR_MSG="${COMMAND}: you must provide an argument for service '${SERVICE}'"
                PARSE_ERR=1
            fi
            ;;
      esac
      ;;
  "reset"|"claim")
      if [ "${SERVICE}" != "plex" ] ; then
          ERR_MSG="${COMMAND}: command is not allowed for service '${SERVICE}'"
          PARSE_ERR=1
      fi
      ;;
esac

if [ ${PARSE_ERR} -ne 0 ] ; then
    usage ; exit 1
fi


# TERM dimensions
if [ "${USE_UI}" != "no" ] ; then
    max_lines="$( tput lines )"
    max_columns="$( tput cols )"
fi

# Store menu options selected by the user
INPUT="/tmp/${SC_NAME}.in.$$"
# Storage file for displaying commands output
OUTPUT="/tmp/${SC_NAME}.out.$$"
# Storage file for misc data
DATA="/tmp/${SC_NAME}.data.$$"
# Storage file for text data
TEXT="/tmp/${SC_NAME}.text.$$"

# trap and delete temp files
trap "exit_func" SIGHUP SIGINT SIGTERM

#IP="$( ip route get 8.8.8.8 | head -1 | sed -e 's/.*\s*src\s*\([0-9.]*\).*$/\1/' )"
IP="$( ip -o route get to 8.8.8.8 | sed -nre 's/.*\s+src\s+([0-9.]+).*/\1/p' )"
HTTPS_HOST="${IP}"
[ -e "/etc/apache2/sites-enabled/rsbssl_easy_a.seedbox.vip.conf" ] \
    && HTTPS_HOST="$( awk '$1 == "ServerName" {print $NF}' \
                         /etc/apache2/sites-enabled/rsbssl_easy_a.seedbox.vip.conf \
                       | head -1 )"


# -------------------------------------------
# Logging functions
# -------------------------------------------
ENTRY () {
    local cfn="${FUNCNAME[1]}"
    local tstamp="$( date )"
    local msg="> ${cfn} ${FUNCNAME}"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> "${LOGFILE}"
}

RETURN () {
    local cfn="${FUNCNAME[1]}"
    local tstamp="$( date )"
    local msg="< ${cfn} ${FUNCNAME}"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> "${LOGFILE}"
}

INFO () {
    local msg="${1}"
    local tstamp="$( date )"
    echo -e "[${tstamp}] [INFO]\t${msg}" >> "${LOGFILE}"
}

ERROR () {
    local msg="${1}"
    local tstamp="$( date )"
    echo -e "[${tstamp}] [ERROR]\t${msg}" >> "${LOGFILE}"
}


DEBUG () {
    local msg="${1}"
    local tstamp="$( date )"
    echo -e "[${tstamp}] [DEBUG]\t${msg}" >> ${LOGFILE}
}


# Capitalize the first letter of the argument
_ucfirst () {
    echo "${1}" | sed -e 's/\([a-z]\)\([a-zA-Z0-9]*\)/\u\1\2/g'
}


#
# Purpose - echo the backtitle string in form 'Backtitle ... spaces ... [_VER]'
#
_backtitle () {
    local v_len
    local t_len
    t_len=$( echo "${1}" | wc -c )
    v_len=$( echo "${_VER}" | wc -c )
    printf "%s%$(( max_columns - t_len - v_len ))s%s" "${1}" " " "${_VER}"
}


_dialog_msgbox () {
    local t="${1}"                  # box title 
    local b="${2}"                  # backtitle
    local m="${3}"                  # box content
    local bt

    bt="${APP_TITLE}"
    [ -n "${b}" ] && bt="${bt}: ${b}"

    dialog \
        ${DIALOG_OPTS} \
        --aspect 14 \
        --title "${t}" \
        --backtitle "$( _backtitle "${bt}" )" \
        --scrollbar \
        --msgbox "${m}" \
        0 0

    return 0
}


_dialog_infobox () {
    local t="${1}"                  # box title 
    local b="${2}"                  # backtitle
    local m="${3}"                  # box content
    local bt

    bt="${APP_TITLE}"
    [ -n "${b}" ] && bt="${bt}: ${b}"

    dialog \
        ${DIALOG_OPTS} \
        --aspect 14 \
        --title "${t}" \
        --backtitle "$( _backtitle "${bt}" )" \
        --infobox "${m}" \
        0 0

    return 0
}


_dialog_textbox () {
    local t="${1}"                  # box title 
    local b="${2}"                  # backtitle
    local m="${3}"                  # box content
    local bt

    bt="${APP_TITLE}"
    [ -n "${b}" ] && bt="${bt}: ${b}"

    echo -e "${m}" | expand > "${TEXT}"

    dialog \
        ${DIALOG_OPTS} \
        --aspect 14 \
        --title "${t}" \
        --backtitle "$( _backtitle "${bt}" )" \
        --exit-label "OK" \
        --scrollbar \
        --textbox "${TEXT}" \
        0 0

    return 0
}


_dialog_please_wait () {
    local t="${1}"                  # box title 
    local b="${2}"                  # backtitle

    _dialog_infobox "${t}" "${b}" "\n      Please wait      \n\n"

    return 0
}


_dlg_url_text () {
    echo "\Zu\Z4${1}\Zn"
}


#
# Purpose - get service help text for the service described by short description
# f.e. _get_svc_help "DelugeD" -> "https://###IP###/deluge"
#
_get_svc_help () {
    local _svc_descr
    local _svc_help=""
    local _port
    if [ -z "${1}" ] ; then
        echo "" ; return
    fi
#    _svc_descr="$( echo "${1}" | tr '[:upper:]' '[:lower:]' )"
    _svc_descr="${1,,}"
    case "${_svc_descr}" in
      "apache")
          _svc_help="https://###IP###" ;;
      "ariang")
          _svc_help="https://###IP###/ariang"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "autobrr")
          _svc_help="https://###IP###/autobrr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "autodl")
          _svc_help="https://github.com/autodl-community/autodl-rutorrent" ;;
      "bazarr")
          _svc_help="https://###IP###/bazarr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "cherrymusic")
          _svc_help="https://###IP###/cherrymusic"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "cloudcmd")
          _svc_help="https://###IP###/cloudcmd"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "cloudtorrent")
          _svc_help="https://cloudtorrent-###IP###"
          ;;
      "couchpotato")
#          _svc_help="https://github.com/CouchPotato/CouchPotatoServer/" ;;
          _svc_help="http://###IP###:$(( USERUID - FIRST_UID + 5050 ))" ;;
      "cuberite")
          _svc_help="https://cuberite-###IP###"
          ;;
      "deluged")
          _svc_help="https://###IP###/deluge"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "delugeweb")
          _svc_help="https://###IP###/deluge"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
#      "docker")
#          _svc_help="" ;;
      "emby")
          _svc_help="http://###IP###:8096" ;;
      "filebrowser")
          _svc_help="https://###IP###/filebrowser"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "filecommander")
          _svc_help="https://###IP###/files"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "flood")
          _svc_help="https://###IP###/flood"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "ftpd")
          _svc_help="http://www.pureftpd.org/" ;;
      "jackett")
          _svc_help="http://###IP###:$(( USERUID - FIRST_UID + 9117 ))" ;;
      "jellyfin")
          _svc_help="http://###IP###:8096 https://###IP###:8920" ;;
      "lidarr")
          _svc_help="https://###IP###/lidarr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "madsonic")
          _svc_help="https://###IP###/madsonic" ;;
#      "mysql")
#          _svc_help="" ;;
      "nginx")
          _svc_help="https://${HTTPS_HOST}/" ;;
#      "nomachine")
#          _svc="nxserver" ;;
      "nzbget")
          _svc_help="https://###IP###/nzbget"
          if [ ! -d "/home/${USERNAME}/.config/nzbget" -a -d "/home/${USERNAME}/.config/nzbgetcom" ] ; then
              _svc_help="https://###IP###/nzbgetcom"
          fi
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "nzbhydra2")
          _svc_help="https://###IP###/nzbhydra"
          ;;
      "ombi")
          _svc_help="https://###IP###/ombi" ;;
      "openvpn")
          _svc_help="http://www.openvpn.net/" ;;
      "overseerr")
          _svc_help="https://overseerr-###IP###" ;;
      "plex")
          _svc_help="http://###IP###:32400/web" ;;
#      "plexpy")
#          _svc="plexpy" ;;
      "prowlarr")
          _svc_help="https://###IP###/prowlarr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "puppeteer")
          _svc_help="https://pp-${HTTPS_HOST}/" ;;
      "pyload")
          _svc_help="https://github.com/pyload/pyload" ;;
      "qbittorrent")
          _svc_help="https://###IP###/qbittorrent"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "radarr")
          _svc_help="https://###IP###/radarr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "rclonewebui")
          _svc_help="https://###IP###/rclone" ;;
      "readarr")
          _svc_help="https://###IP###/readarr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "resiliosync")
          RSLSYNC_PORT="$(( USERUID + 8888 - FIRST_UID ))"
          _svc_help="https://###IP###:${RSLSYNC_PORT}"
#          _svc_help="https://www.resilio.com/"
          ;;
      "rtorrent")
          _svc_help="https://###IP###/rutorrent"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "sabnzbd")
          _svc_help="https://###IP###/sabnzbd"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "sickbeard")
          _svc_help="http://###IP###:8081" ;;
      "sickrage")
#          _svc_help="http://###IP###:8082" ;;
          _svc_help="http://###IP###/sickrage" ;;
      "sickchill")
          _svc_help="http://###IP###/sickchill" ;;
      "simpletorrent")
          _svc_help="https://simpletorrent-###IP###"
          ;;
      "softethervpn")
          _svc_help="###IP###:5555 ; https://www.softether.org/" ;;
      "sonarr")
          _svc_help="https://###IP###/sonarr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "sonarrlatest")
          _svc_help="https://###IP###/sonarr-latest"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "ssh"|"sshd")
          _port="$( grep -m1 -E '^Port\s+' /etc/ssh/sshd_config | awk '{print $2}' )"
          [ -z "${_port}" ] && _port="22"
          _svc_help="###IP###:${_port}" ;;
      "storm")
          _svc_help="https://###IP###/storm"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "subsonic")
          _svc_help="https://###IP###/subsonic" ;;
      "syncthing")
          _svc_help="https://syncthing-###IP###"
          ;;
      "tautulli")
          _svc_help="http://###IP###:8181" ;;
      "thinlincweb")
          _svc_help="https://###IP###:300" ;;
      "transmission")
          _svc_help="https://###IP###/transmission"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "vnc")
          _svc_help="https://www.tightvnc.com" ;;
      "webssh")
          _svc_help="https://###IP###/ssh" ;;
      "whisparr")
          _svc_help="https://###IP###/whisparr"
          if [ ${USERUID} -ne ${FIRST_UID} ] ; then
              _svc_help="${_svc_help}-${USERNAME}"
          fi
          ;;
      "wiztorrent")
          _svc_help="https://wt-###IP###" ;;
      "xrdp")
          _svc_help="http://xrdp.org/" ;;
      "3proxy")
          _svc_help="###IP###:3128" ;;
    esac
    if [ -z "${_svc_help}" ] ; then
        _svc_help="${_svc_descr}"
    else
        case "${_svc_descr}" in
          "resiliosync")
              # -- Display real IP for some services
              _svc_help="$( echo "${_svc_help}" | sed -e "s/###IP###/${IP}/g" )"
              ;;
          *)
              # -- Display a-b-c-d.a.seedbox.vip for other services
              _svc_help="$( echo "${_svc_help}" | sed -e "s/###IP###/${HTTPS_HOST}/g" )"
              ;;
        esac
        _svc_help="$( echo "${_svc_help}" | sed -e "s/###USERNAME###/${USERNAME}/g" )"
    fi
    echo "${_svc_help}"
}


#
# Purpose - get service name for the service described by short description
# f.e. _get_svc_name "DelugeD" -> "deluged@user"
#
_get_svc_name () {
    local _svc_descr
    local _svc=""
    if [ -z "${1}" ] ; then
        echo "" ; return
    fi
    _svc_descr="$( echo "${1}" | tr '[:upper:]' '[:lower:]' )"
    case "${_svc_descr}" in
      "apache")
          case "${LSB_VENDOR}" in
            "CentOS"|"CentOSStream")
                _svc="httpd" ;;
            "Debian"|"Ubuntu")
                _svc="apache2" ;;
          esac ;;
      "ariang")
          _svc="ariang@${USERNAME}" ;;
      "autobrr")
          _svc="autobrr@${USERNAME}" ;;
      "autodl")
          _svc="irssi@${USERNAME}" ;;
      "bazarr")
          _svc="bazarr@${USERNAME}" ;;
      "btsync")
          _svc="btsync@${USERNAME}" ;;
      "cherrymusic")
          _svc="cherrymusic@${USERNAME}" ;;
      "cloudcmd")
          _svc="cloudcmd@${USERNAME}" ;;
      "cloudtorrent")
          _svc="cloud-torrent@${USERNAME}" ;;
      "couchpotato")
          _svc="couchpotato@${USERNAME}" ;;
      "cuberite")
          _svc="cuberite@${USERNAME}" ;;
      "deluged")
          _svc="deluged@${USERNAME}" ;;
      "delugeweb")
          _svc="deluge-web@${USERNAME}" ;;
      "docker")
          _svc="docker" ;;
      "emby")
          _svc="emby-server" ;;
      "filebrowser")
          _svc="filebrowser@${USERNAME}" ;;
      "filecommander")
          _svc="filecommander@${USERNAME}" ;;
      "flood")
          _svc="flood@${USERNAME}" ;;
      "ftpd")
          _svc="pure-ftpd" ;;
      "jackett")
          _svc="jackett@root"
          if [ -e "${USERHOME}/.config/Jackett/ServerConfig.json" ] ; then
              _svc="jackett@${USERNAME}"
          elif [ -e "/root/.config/Jackett/ServerConfig.json" ] ; then
              _svc="jackett@root"
          fi ;;
      "jellyfin")
          _svc="jellyfin" ;;
      "lidarr")
          _svc="lidarr@${USERNAME}" ;;
      "madsonic")
          _svc="madsonic" ;;
      "mysql")
          _svc="mysql" ;;
      "nginx")
          _svc="nginx" ;;
      "nomachine")
          _svc="nxserver" ;;
      "nzbget")
          _svc="nzbget@${USERNAME}"
          if [ ! -e "/etc/systemd/system/nzbget@.service" -a -e "/etc/systemd/system/nzbgetcom@.service" ] ; then
              _svc="nzbgetcom@${USERNAME}"
          elif [ ! -d "/home/${USERNAME}/.config/nzbget" -a -d "/home/${USERNAME}/.config/nzbgetcom" ] ; then
              _svc="nzbgetcom@${USERNAME}"
          fi
          ;;
      "nzbhydra2")
          _svc="nzbhydra2@${USERNAME}" ;;
      "ombi")
          _svc="ombi" ;;
      "openvpn")
          _svc="openvpn@rsb-server" ;;
      "overseerr")
          _svc="snap.overseerr.daemon" ;;
      "plex")
          _svc="plexmediaserver" ;;
      "plexpy")
          _svc="plexpy" ;;
      "prowlarr")
          _svc="prowlarr@${USERNAME}" ;;
      "puppeteer")
          _svc="puppeteer" ;;
      "pyload")
          _svc="pyload" ;;
      "qbittorrent")
          _svc="qbittorrent@${USERNAME}" ;;
      "radarr")
          _svc="radarr@${USERNAME}" ;;
      "rclonewebui")
          _svc="rclonewebui@${USERNAME}" ;;
      "readarr")
          _svc="readarr@${USERNAME}" ;;
      "resiliosync")
          _svc="resilio-sync@${USERNAME}" ;;
      "rtorrent")
          _svc="rtorrent@${USERNAME}" ;;
      "sabnzbd")
          if [ -e "${USERHOME}/.sabnzbd/sabnzbd.ini" ] ; then
              _svc="sabnzbd@${USERNAME}"
          elif [ -e "/root/.sabnzbd/sabnzbd.ini" ] ; then
              _svc="sabnzbd@root"
          fi ;;
      "sickbeard")
          _svc="sickbeard@root" ;;
      "sickrage")
#          _svc="sickrage@root" ;;
          _svc="sickrage@${USERNAME}" ;;
      "sickchill")
          _svc="sickchill@${USERNAME}" ;;
      "simpletorrent")
          _svc="simple-torrent@${USERNAME}" ;;
      "softethervpn")
          _svc="vpnserver" ;;
      "sonarr")
          _svc="sonarr@${USERNAME}" ;;
      "sonarrlatest")
          _svc="sonarr-latest@${USERNAME}" ;;
      "ssh"|"sshd")
          case "${LSB_VENDOR}" in
            "CentOS"|"CentOSStream")
                _svc="sshd" ;;
            "Ubuntu"|"Debian")
                _svc="ssh" ;;
          esac
          ;;
      "storm")
          _svc="storm@${USERNAME}" ;;
      "subsonic")
          _svc="subsonic" ;;
      "syncthing")
          if [ -e "${USERHOME}/.config/syncthing/config.xml" ] ; then
              _svc="syncthing@${USERNAME}"
          elif [ -e "/root/.config/syncthing/config.xml" ] ; then
              _svc="syncthing@root"
          fi
          ;;
      "tautulli")
          _svc="tautulli" ;;
      "thinlincweb")
          _svc="tlwebaccess" ;;
      "transmission")
          _svc="transmission-daemon@${USERNAME}" ;;
      "utorrent")
          _svc="utserver@${USERNAME}" ;;
      "vnc")
          _svc="vncserver-${USERNAME}" ;;
      "webssh")
          _svc="webssh" ;;
      "whisparr")
          _svc="whisparr@${USERNAME}" ;;
      "wiztorrent")
          _svc="rsb-wiztorrent@${USERNAME}" ;;
      "xrdp")
          _svc="xrdp" ;;
      "3proxy")
          _svc="3proxy" ;;
    esac
    echo "${_svc}"
}


#
# Purpose - get monitored service name for the service described by the `systemd` service name
# f.e. _get_svc_monit_name "deluged@user" -> "deluge-user"
#
_get_svc_monit_name () {
    local _svc="${1}"
    local _svc_monit
    local _svc_monit_file=""
    if [ -z "${_svc}" ] ; then
        echo "non-existent" ; return
    fi
    case "${_svc}" in
      "ssh"|"sshd")
          _svc="ssh"
          ;;
    esac
    if [ -e "/etc/monit/conf.d/${_svc}" ] ; then
        _svc_monit_file="/etc/monit/conf.d/${_svc}"
    else
        _svc_monit=$( echo "${_svc}" | tr '@' '-' )
        if [ ! -e "/etc/monit/conf.d/${_svc_monit}" ] ; then
            _svc_monit="non-existent"
        else
            _svc_monit_file="/etc/monit/conf.d/${_svc_monit}"
        fi
    fi
    if [ -n "${_svc_monit_file}" ] ; then
        _svc_monit="$( grep -m 1 -E "^check\s+process" "${_svc_monit_file}" | awk '{print $3}' )"
    else
        _svc_monit="non-existent"
    fi
    echo "${_svc_monit}"
}


_claim_plex () {

    local _bt
    local _ret

    _bt="$( _backtitle "${APP_TITLE}: Claim Plex Media Server" )"

    # get key
    rm -vf "${DATA}" >> "${LOGFILE}" 2>&1
    dialog ${DIALOG_OPTS} \
           --aspect 14 \
           --backtitle "${_bt}" \
           --title "" \
           --ok-label "Claim" \
           --inputbox \
             "Visit $( _dlg_url_text "https://www.plex.tv/claim/" ) and copy the claim code to the clipboard.\n\
Paste the code:" \
        0 0 2> "${DATA}"
    _ret=$?
    [ ${_ret} -eq ${DIALOG_CANCEL} -o ${_ret} -eq ${DIALOG_ESC} ] \
        && return ${_ret}

    if [ "${USE_UI}" = "yes" ] ; then
        _dialog_please_wait \
             "Claiming Plex" \
             "${_bt}"
        /usr/local/bin/claim-plex "$( cat "${DATA}" )" > "${TEXT}" 2>&1
        _dialog_msgbox \
             " Claim status " \
             "${_bt}" \
             "$( cat "${TEXT}" )"
    else
        /usr/local/bin/claim-plex "$( cat "${DATA}" )" > /dev/null 2>&1
    fi
    _ret=$?

    return ${ret}
}


_claim_plex_unattended () {

    local _claim_token="${1}"
    local _ret

    INFO "Claiming Plex with token [${_claim_token}]"
    /usr/local/bin/claim-plex "${_claim_token}" >> "${LOGFILE}" 2>&1
    _ret=$?

    return ${ret}
}


_get_plex_claim_status () {

    local _plex_token
    local _rc=1

    _plex_token="$( grep 'PlexOnlineToken=' \
                    ~plex/Library/Application\ Support/Plex\ Media\ Server/Preferences.xml \
                   | sed -e 's|^.*PlexOnlineToken="\([^"]*\)".*$|\1|g' \
                 )"
    if [ -n "${_plex_token}" ] ; then
        if wget -q -O /dev/null \
               "https://plex.tv/media/providers?X-Plex-Token=${_plex_token}" 2> /dev/null
        then
            _rc=0
        fi
    fi

    return "${_rc}"
}


#
# Purpose - get "Running" service instance's MainPID
# f.e. _get_svc_pid "deluged@user"
#
_get_svc_pid () {
    local _svc="${1}"
    local _pid=""
    case "${_svc}" in
      "apache2")
          if [ -e "/var/run/apache2/apache2.pid" ] ; then
              _pid="$( cat "/var/run/apache2/apache2.pid" )"
          fi
          ;;
      "pure-ftpd")
          if [ -e "/var/run/pure-ftpd.pid" ] ; then
              _pid="$( cat "/var/run/pure-ftpd.pid" )"
          elif [ -e "/var/run/pure-ftpd/pure-ftpd.pid" ] ; then
              _pid="$( cat "/var/run/pure-ftpd/pure-ftpd.pid" )"
          fi
          ;;
      *)
          _pid="$( systemctl show "${_svc}" -p MainPID | awk -F '=' '{print $2}' )"
          ;;
    esac
    echo "${_pid}"
}


#
# Purpose - services operations
# f.e. _process_svc "deluged@user" start
#
_process_svc () {
    local _ret=0
    local _bt
    local _svc
    local _svc_list
    local _op
    local _svc_monit
    local _auth_key
    local _menu_arr
    local _item
    local _json_msg="OK"

    _svc="${1}"
#    _op="$( echo "${2}" | tr '[:upper:]' '[:lower:]' )"
    _op="${2,,}"
    _svc_monit="$( _get_svc_monit_name "${_svc}" )"
    _bt="${_op} ${_svc}"

    case "${_svc}" in
#      "docker")
#          _svc_list="docker containerd docker.socket"
#          ;;
      *)
          _svc_list="${_svc}"
          ;;
    esac

    for _svc in ${_svc_list} ; do
        case "${_op}" in
          "status")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Processing '${_svc}' service" \
                      "${_bt}"
                  systemctl --no-pager --full -l status "${_svc}" 2>&1 \
                      | iconv -f UTF8 -t ASCII//TRANSLIT > "${TEXT}"
                  _ret=$?
                  _dialog_msgbox \
                      "Status for '${_svc}' service" \
                      "${_bt}" \
                      "$( cat "${TEXT}" )"
              else
                  /usr/local/bin/_svc status "${_svc}" > /dev/null 2>&1
                  _ret=$?
              fi
              ;;
          "restart")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Restarting '${_svc}' service" \
                      "${_bt}"
              fi
              /usr/local/bin/_svc restart "${_svc}" > /dev/null 2>&1
              _ret=$?
              ;;
          "start")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Starting '${_svc}' service" \
                      "${_bt}"
              fi
              /usr/local/bin/_svc start "${_svc}" > /dev/null 2>&1
              _ret=$?
              ;;
          "stop")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Stopping '${_svc}' service" \
                      "${_bt}"
              fi
              /usr/local/bin/_svc stop "${_svc}" > /dev/null 2>&1
              _ret=$?
              ;;
          "enable")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Enabling '${_svc}' service" \
                      "${_bt}"
              fi
              /usr/local/bin/_svc enable "${_svc}" > /dev/null 2>&1
              _ret=$?
              ;;
          "disable")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Disabling '${_svc}' service" \
                      "${_bt}"
              fi
              /usr/local/bin/_svc disable "${_svc}" > /dev/null 2>&1
              _ret=$?
              ;;
          "monitor")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Enabling minitoring for '${_svc}' service" \
                      "${_bt}"
              fi
              monit monitor "${_svc_monit}" > /dev/null 2>&1
              _ret=$?
              ;;
          "unmonitor")
              if [ "${USE_UI}" = "yes" ] ; then
                  _dialog_please_wait \
                      "Disabling minitoring for '${_svc}' service" \
                      "${_bt}"
              fi
              monit unmonitor "${_svc_monit}" > /dev/null 2>&1
              _ret=$?
              ;;
          "claim")
              if [ "${USE_UI}" = "yes" ] ; then
                  _claim_plex
                  _ret=$?
              else
                  _claim_plex_unattended "${EXTRA_ARGS}"
                  _ret=$?
              fi
              ;;
          "reset")
              if [ "${_svc}" = "plexmediaserver" ] ; then
                  if [ "${USE_UI}" = "yes" ] ; then
                      _dialog_please_wait \
                          "Resetting Plex" \
                          "${_bt}"
                      /usr/local/bin/reset-plex
                      _ret=$?
                  else
                      /usr/local/bin/reset-plex -f > /dev/null 2>&1
                      _ret=$?
                  fi
              fi
              ;;
          "enable root login"|"root-enable")
              if grep -q -i -E '^permitrootlogin' /etc/ssh/sshd_config 2> /dev/null ; then
                  sed -i -re 's/^(permitrootlogin)\s+.*/\1 yes/Ig' /etc/ssh/sshd_config
              else
                  echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
              fi
              systemctl restart sshd
              _ret=$? 
              ;;
          "disable root login"|"root-disable")
              if grep -q -i -E '^permitrootlogin' /etc/ssh/sshd_config 2> /dev/null ; then
                  sed -i -re 's/^(permitrootlogin)\s+.*/\1 prohibit-password/Ig' /etc/ssh/sshd_config
              else
                  echo "PermitRootLogin prohibit-password" >> /etc/ssh/sshd_config
              fi
              systemctl restart sshd
              _ret=$? 
              ;;
          "add root authorized key"|"root-key-add")
              if [ "${USE_UI}" = "yes" ] ; then
                  rm -f "${INPUT}"
                  touch "${INPUT}"
                  dialog ${DIALOG_OPTS} \
                         --backtitle "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                         --title "  >>> Enter Authorized Key <<<  " \
                         --inputbox "" \
                         8 65 2> "${INPUT}"
                  _ret=$? 
                  _auth_key="$( cat "${INPUT}" )"
                  if    [ ${_ret} -ne $DIALOG_CANCEL ] \
                     && [ ${_ret} -ne $DIALOG_ESC ] \
                     && [ -n "${_auth_key}" ]
                  then
                      if ! ssh-keygen -l -f "${INPUT}" > /dev/null 2>&1 ; then
                          _dialog_msgbox \
                              "  !!! Invalid Authorized Key !!!  " \
                              "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                              "${_auth_key}"
                              _ret=1
                              _json_msg="Invalid Authorized Key"
                      else
                          if grep -q "^${_auth_key}$" /root/.ssh/authorized_keys
                          then
                              _json_msg="Authorized Key is already there"
                              _dialog_msgbox \
                                  "  !!! ${_json_msg} !!!  " \
                                  "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                                  "\nKey info:\n---------\n\n$( ssh-keygen -l -f /dev/stdin <<< "${_auth_key}" )\n\n"
                              _ret=1
                          else
                              echo "${_auth_key}" >> /root/.ssh/authorized_keys
                              chmod 700 /root/.ssh > /dev/null 2>&1
                              chmod 600 /root/.ssh/authorized_keys > /dev/null 2>&1
                              _json_msg="Authorized Key successfully added"
                              _dialog_msgbox \
                                  "  *** ${_json_msg} ***  " \
                                  "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                                  "\nKey info:\n---------\n\n$( ssh-keygen -l -f /dev/stdin <<< "${_auth_key}" )\n\n"
                              _ret=0
                          fi
                      fi
                  fi
              else
                  # -- CLI operation
                  _auth_key="${EXTRA_ARGS}"
                  if ! ssh-keygen -l -f /dev/stdin <<< "${_auth_key}" > /dev/null 2>&1
                  then
                      _ret=1
                      _json_msg="Invalid Authorized Key"
                  else
                      if grep -q "^${_auth_key}$" /root/.ssh/authorized_keys ; then
                          _ret=1
                          _json_msg="Authorized Key is already there"
                      else
                          echo "${_auth_key}" >> /root/.ssh/authorized_keys
                          chmod 700 /root/.ssh > /dev/null 2>&1
                          chmod 600 /root/.ssh/authorized_keys > /dev/null 2>&1
                          _ret=0
                          _json_msg="Authorized Key successfully added"
                      fi
                  fi
              fi
              ;;
          "delete root authorized key"|"root-key-del")
              if [ "${USE_UI}" = "yes" ] ; then
                  while true ; do
                      grep -v -E \
                          '\s+Ansible master key for RapidSeedbox.com$|\s+RapidSeedbox WHMCS Installer$' \
                          "/root/.ssh/authorized_keys" > "${DATA}"
                      [ ! -s "${DATA}" ] && break
                      _menu_arr=()
                      while read _auth_key ; do
                          _menu_arr+=( "$( ssh-keygen -l -f /dev/stdin <<< "${_auth_key}" )" "" )
                      done < "${DATA}"
                      dialog ${DIALOG_OPTS} \
                         --backtitle "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                         --title "   Choose the key   " \
                         --ok-label " Delete " \
                         --cancel-label " << Back" \
                         --menu "" \
                         0 0 0 \
                         "${_menu_arr[@]}" \
                       2> "${INPUT}"
                      _ret=$?
                      [ ${_ret} -eq ${DIALOG_CANCEL} -o ${_ret} -eq ${DIALOG_ESC} ] && break
                      _item="$( cat "${INPUT}" )"
                      dialog ${DIALOG_OPTS} \
                         --backtitle "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                         --aspect 14 \
                         --defaultno \
                         --title "  Are you sure you want to delete the key?  " \
                         --yesno "\n\n${_item}\n\n" \
                         0 0 \
                       || continue
                      # -- Delete the key -- #
                      rm -f /root/.ssh/authorized_keys.tmp.$$ > /dev/null 2>&1
                      touch /root/.ssh/authorized_keys.tmp.$$ > /dev/null 2>&1
                      while read _auth_key ; do
                          [ "$( ssh-keygen -l -f /dev/stdin <<< "${_auth_key}" )" = "${_item}" ] \
                              && continue
                          echo "${_auth_key}"
                      done < "/root/.ssh/authorized_keys" >> /root/.ssh/authorized_keys.tmp.$$
                      mv -f /root/.ssh/authorized_keys.tmp.$$ /root/.ssh/authorized_keys > /dev/null 2>&1
                      chmod 700 /root/.ssh > /dev/null 2>&1
                      chmod 600 /root/.ssh/authorized_keys > /dev/null 2>&1
                      _json_msg="Authorized Key successfully deleted"
                      _dialog_msgbox \
                          "  *** Success ***  " \
                          "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
                          "\n\n   ${_json_msg}   \n\n"
                  done
              else
                  # -- CLI operation
                  _auth_key="${EXTRA_ARGS}"
                  if ! ssh-keygen -l -f /dev/stdin <<< "${_auth_key}" > /dev/null 2>&1
                  then
                      _ret=1
                      _json_msg="Invalid Authorized Key"
                  else
                      if ! grep -q "^${_auth_key}$" /root/.ssh/authorized_keys ; then
                          _ret=1
                          _json_msg="Authorized Key not found"
                      else
                          grep -v "${_auth_key}" /root/.ssh/authorized_keys \
                                 > /root/.ssh/authorized_keys.tmp.$$
                          _ret=$?
                          mv -f /root/.ssh/authorized_keys.tmp.$$ /root/.ssh/authorized_keys > /dev/null 2>&1
                          chmod 700 /root/.ssh > /dev/null 2>&1
                          chmod 600 /root/.ssh/authorized_keys > /dev/null 2>&1
                          _json_msg="Authorized Key successfully deleted"
                      fi
                  fi
              fi
              ;;
          *)
              _json_msg="Unknown command: ${_op}"
              _ret=100
              ;;
        esac
    done

    if [ ${_ret} -ne 0 ] ; then
        echo "{\"status\": \"error\",\"code\":\"${_rc}\",\"message\":\"${_json_msg}\"}" \
            > "${DATA}"
    else
        echo "{\"status\": \"success\",\"code\":\"${_rc}\",\"message\":\"${_json_msg}\"}" \
            > "${DATA}"
    fi

    return ${_ret}
}


#
# Purpose - get service status (displayed in the main menu on the 2nd column)
# f.e. _get_svc_status "DelugeD" -> "Running, Start on boot Enabled, Monitored"
#
_get_svc_status () {
    local _status
    local _svc
    local _svc_monit
    local _state
    local _monit
    local _enabled
    local _plex_token
    local _plex_claim_status
    local _root_login

    if [ -z "${1}" ] ; then
        echo "" ; return
    fi

    _svc="$( _get_svc_name "${1}" )"
    _svc_monit="$( _get_svc_monit_name "${_svc}" )"
    _state="$( _ucfirst "$( systemctl show -p SubState "${_svc}" 2> /dev/null \
              | awk -F'=' '{print $NF}' \
              | tr '[:upper:]' '[:lower:]' )" )"
    [ "${_state}" = "Dead" ] && _state="Stopped"
    _enabled="$( _ucfirst "$( systemctl is-enabled "${_svc}" 2> /dev/null \
              | tr '[:upper:]' '[:lower:]' )" )"
    _monit=""
    if    which monit > /dev/null 2>&1 \
       && systemctl is-active "monit" > /dev/null 2>&1
    then
        if [ "${_svc_monit}" != "non-existent" ] ; then
            _monit="$( _ucfirst "$( monit status "${_svc_monit}" 2> /dev/null \
                                        | grep -E '^\s*monitoring\s+status' \
                                        | sed -e 's/^\s*monitoring\sstatus\s*\(.*\)$/\1/g' \
                                        | tr '[:upper:]' '[:lower:]' )" \
                     )"
        fi
        if [ -z "${_monit}" ] ; then
            if [ -e "/etc/monit/tmp/${_svc}" ] ; then
                _monit=", Monitoring disabled"
            fi
        else
            _monit=", ${_monit}"
        fi
    fi
    _status="${_state}, Start on boot ${_enabled}${_monit}"

    case "${_svc}" in
      "plexmediaserver")
          _plex_claim_status="NOT claimed"
          _plex_token="$( grep 'PlexOnlineToken=' \
                      ~plex/Library/Application\ Support/Plex\ Media\ Server/Preferences.xml \
                    | sed -e 's|^.*PlexOnlineToken="\([^"]*\)".*$|\1|g' )"
          if [ -n "${_plex_token}" ] ; then
              wget -q -O /dev/null "https://plex.tv/media/providers?X-Plex-Token=${_plex_token}" \
                  && _plex_claim_status="Claimed"
          fi
          _status="${_status}, ${_plex_claim_status}"
          ;;
      "ssh"|"sshd")
          _root_login="$( sshd -T | grep -i -E '^permitrootlogin\s+' | awk '{print $NF}' )"
          _status="${_status}, Root login: ${_root_login}"
          ;;
    esac

    echo "${_status}"
}


#
# Purpose - service operations submenu
# f.e. _menu_svc "DelugeD"
#
_menu_svc () {
    local _svc
    local _svc_name
    local _svc_descr
    local _svc_monit
    local _state
    local _monit
    local _enabled
    local _plex_token
    local _root_login
    local _ret
    local _menuitem
    local _default_item=""
    local ar_svc
    local _num
    local _cnt
    _svc_name="${1}"
    _svc="$( _get_svc_name "${_svc_name}" )"
    _svc_monit="$( _get_svc_monit_name "${_svc}" )"
    while : ; do
        ar_svc=()
        _state="$( _ucfirst "$( systemctl show -p SubState "${_svc}" 2> /dev/null \
                  | awk -F'=' '{print $NF}' \
                  | tr '[:upper:]' '[:lower:]' )" )"
        [ "${_state}" = "Dead" ] && _state="Stopped"
        _enabled="$( _ucfirst "$( systemctl is-enabled "${_svc}" 2> /dev/null \
                  | tr '[:upper:]' '[:lower:]' )" )"
        _monit=""
        if [ "${_svc_monit}" != "non-existent" ] ; then
            _monit="$( _ucfirst "$( monit status "${_svc_monit}" 2> /dev/null \
                      | grep -E '^\s*monitoring\s+status' \
                      | sed -e 's/^\s*monitoring\sstatus\s*\(.*\)$/\1/g' \
                      | tr '[:upper:]' '[:lower:]' )" )"
        fi
        ar_svc+=("Status" "| Show '${_svc}' status" "\Zb\Z3Show status for \Z1${_svc}\Z3 service\Zn")
        case "${_svc}" in
          "ssh"|"sshd")
              _root_login="$( sshd -T | grep -i -E '^permitrootlogin\s+' | awk '{print $NF}' )"
              if [ "${_root_login}" != "yes" ] ; then
                  ar_svc+=("Enable Root login" "|"  "\Zb\Z3Enable \Z1root\Z3 login\Zn")
              else
                  ar_svc+=("Disable Root login" "|"  "\Zb\Z3Disable \Z1root\Z3 login\Zn")
              fi
              ar_svc+=("Add Root authorized key" "|" "\Zb\Z3Add \Z1root\Z3 authorized key\Zn")
              if [ -e "/root/.ssh/authorized_keys" ] ; then
                  _cnt="$( grep -v -E '\s+Ansible master key for RapidSeedbox.com$|\s+RapidSeedbox WHMCS Installer$' /root/.ssh/authorized_keys | wc -l )"
                  if [ ${_cnt} -ne 0 ] ; then
                      ar_svc+=("Delete Root authorized key" "|" "\Zb\Z3Delete \Z1root\Z3 authorized key\Zn")
                  fi
              fi
              ;;
          *)
              if [ "${_state}" = "Running" ] ; then
                  ar_svc+=("Restart" "| ${_state}"  "\Zb\Z3Restart \Z1${_svc}\Z3 service\Zn")
                  ar_svc+=("Stop" "| ${_state}" "\Zb\Z3Stop \Z1${_svc}\Z3 service\Zn")
              else
                  ar_svc+=("Start" "| ${_state}" "\Zb\Z3Start \Z1${_svc}\Z3 service\Zn")
              fi
              if [ "${_enabled}" = "Enabled" ] ; then
                  ar_svc+=("Disable" "| Start on boot Enabled" "\Zb\Z3Do not start \Z1${_svc}\Z3 service on VPS boot\Zn")
              else
                  ar_svc+=("Enable" "| Start on boot Disabled" "\Zb\Z3Enable start of \Z1${_svc}\Z3 service on VPS boot\Zn")
              fi
              if [ "${_monit}" = "Monitored" ] ; then
                  ar_svc+=("Unmonitor" "| Monitored" "\Zb\Z3Do not monitor the status of \Z1${_svc}\Z3 service\Zn")
              else
                  if [ -n "${_monit}" ] ; then
                      ar_svc+=("Monitor" "| Not monitored" "\Zb\Z3Monitor the status of \Z1${_svc}\Z3 service\Zn")
                  fi
              fi
              if [ "${_svc}" = "plexmediaserver" ] ; then
                  if _get_plex_claim_status ; then
                      ar_svc+=("Reset" "| Clear configuration" "\Zb\Z3Reset \Z1${_svc}\Z3\Zn")
                  else
                      ar_svc+=("Claim" "|" "\Zb\Z3Claim \Z1${_svc}\Z3\Zn")
                  fi
              fi
        esac

        #
        ### display service operations menu ###
        _num="${#ar_svc[@]}"
        _num="$(( _num / 2 ))"
        dialog \
            ${DIALOG_OPTS} \
            --backtitle "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
            --title " ${_svc_name} Service " \
            --cancel-label " << Back" \
            --default-item "${_default_item}" \
            --item-help \
            --menu "You can use the UP/DOWN arrow keys, the first \n\
letter of the choice as a hot key. \n\
Choose the TASK" $((_num+10)) 0 ${_num} \
            "${ar_svc[@]}" 2>"${INPUT}"
        _ret=$?
        [ ${_ret} -eq ${DIALOG_CANCEL} -o ${_ret} -eq ${DIALOG_ESC} ] && break
        _menuitem=$(<"${INPUT}")
        _default_item="${_menuitem}"
        _process_svc "${_svc}" "${_menuitem}"
    done
}


_process_svc_unattended () {
    local _ret
    local _message
    local _result_msg
    local _result_code
    local _data
    local _s_body
    local _svc_descr
    local _svc_command
    local _svc
    local _svc_monit
    local _state
    local _monit
    local _enabled
    local _root_login
    local _auth_key
    local _auth_key_tmp=""
    _svc_descr="${1}"
    _svc_command="${2}"
    _svc="$( _get_svc_name "${_svc_descr}" )"
    if [ -z "${_svc}" ] ; then
        case "${FORMAT}" in
          "json")
              cat <<-EOF
		{
		"description":"${_svc_descr}",
		"result":"error",
		"resultmsg":"Service unknown",
		"instance":"Unknown",
		"state":"Unknown"
		}
		EOF
              ;;
          "xml")
              cat <<-EOF
		<service name="${_svc_descr}">
		<result>error</result>
		<resultmsg>Service unknown</resultmsg>
		<instance>Unknown</instance>
		<state>Unknown</state>
		</service>
		EOF
              ;;
        esac
        return
    fi
    # ------------------------------
    _process_svc "${_svc}" "${_svc_command}"
    _ret=$?
    _message="$( jq -r '.message' < "${DATA}" )"
    if [ ${_ret} -eq 0 ] ; then
        _result_msg="success"
    else
        _result_msg="error"
    fi
    _result_code=${_ret}
    [ "${DEBUG}" = "yes" ] \
        && _data="\"data\": $( systemctl status -o json --no-page -n 1 "${_svc}" | grep -e '^{' )"
    # ------------------------------
    _svc_monit="$( _get_svc_monit_name "${_svc}" )"
    _state="$( _ucfirst "$( systemctl show -p SubState "${_svc}" 2> /dev/null \
              | awk -F'=' '{print $NF}' \
              | tr '[:upper:]' '[:lower:]' )" )"
    [ "${_state}" = "Dead" ] && _state="Stopped"
    _enabled="$( _ucfirst "$( systemctl is-enabled "${_svc}" 2> /dev/null \
              | tr '[:upper:]' '[:lower:]' )" )"
    _monit=""
    if [ "${_svc_monit}" != "non-existent" ] ; then
        _monit="$( _ucfirst "$( monit status "${_svc_monit}" 2> /dev/null \
                  | grep -E '^\s*monitoring\s+status' \
                  | sed -e 's/^\s*monitoring\sstatus\s*\(.*\)$/\1/g' \
                  | tr '[:upper:]' '[:lower:]' )" )"
    else
        if [ -e "/etc/monit/tmp/${_svc}" ] ; then
            _monit="Disabled"
        else
            _monit="Unavailable"
        fi
    fi
    if [ "${_STATE_STARTED}" = "yes" -a "${_state}" != "Running" ] ; then
        echo -n "" ; return
    fi
    if [ "${_STATE_STOPPED}" = "yes" -a "${_state}" != "Stopped" ] ; then
        echo -n "" ; return
    fi
    if [ "${_STATE_ENABLED}" = "yes" -a "${_enabled}" != "Enabled" ] ; then
        echo -n "" ; return
    fi
    if [ "${_STATE_DISABLED}" = "yes" -a "${_enabled}" != "Disabled" ] ; then
        echo -n "" ; return
    fi
    # If ${_enabled} is empty - that mean the service is not valid
    if [ -z "${_enabled}" ] ; then
        case "${FORMAT}" in
          "json")
              cat <<-EOF
		{
		"description":"${_svc_descr}",
		"result":"error",
		"resultmsg":"Service unknown",
		"instance":"${_svc}",
		"state":"Unknown"
		}
		EOF
              ;;
          "xml")
              cat <<-EOF
		<service name="${_svc_descr}">
		<result>error</result>
		<resultmsg>Service unknown</resultmsg>
		<instance>${_svc}</instance>
		<state>Unknown</state>
		</service>
		EOF
              ;;
        esac
        return
    fi
    case "${FORMAT}" in
      "json")
          _s_body="{"
          _s_body="${_s_body}\"description\":\"${_svc_descr}\","
          _s_body="${_s_body}\"result\":\"${_result_msg}\","
          _s_body="${_s_body}\"code\":\"${_result_code}\","
          _s_body="${_s_body}\"message\":\"${_message}\","
          _s_body="${_s_body}\"instance\":\"${_svc}\","
          _s_body="${_s_body}\"state\":\"${_state}\","
          [ "${_state}" = "Running" ] \
              && _s_body="${_s_body}\"pid\":\"$( _get_svc_pid "${_svc}" )\","
          _s_body="${_s_body}\"enabled\":\"${_enabled}\","
          _s_body="${_s_body}\"monit\":\"${_monit}\""
          case "${_svc}" in
            "ssh"|"sshd")
                _root_login="$( sshd -T | grep -i -E '^permitrootlogin\s+' | awk '{print $NF}' )"
                _s_body="${_s_body},\"root-login\":\"${_root_login}\""
                _s_body="${_s_body},\"root-keys\":["
                _auth_key_tmp=""
                while read _auth_key ; do
                    echo "${_auth_key}" \
                     | grep -q -E \
                         '\s+Ansible master key for RapidSeedbox.com$|\s+RapidSeedbox WHMCS Installer$' \
                    && continue
                    [ -n "${_auth_key_tmp}" ] && _auth_key_tmp="${_auth_key_tmp},"
                    _auth_key_tmp="${_auth_key_tmp}\"${_auth_key}\""
                done < "/root/.ssh/authorized_keys"
                _s_body="${_s_body}${_auth_key_tmp}]"
                ;;
            "plexmediaserver")
                if _get_plex_claim_status ; then
                    _s_body="${_s_body},\"claimed\":\"yes\""
                else
                    _s_body="${_s_body},\"claimed\":\"no\""
                fi
                ;;
          esac
          [ "${DEBUG}" = "yes" ] \
              && _s_body="${_s_body},${_data}"
          _s_body="${_s_body}}"
          ;;
      "xml")
          _s_body="<service name=\"${_svc_descr}\">"
          _s_body="${_s_body}<result>${_result_msg}</result>"
          _s_body="${_s_body}<code>${_result_code}</code>"
          _s_body="${_s_body}<message>${_message}</message>"
          _s_body="${_s_body}<instance>${_svc}</instance>"
          _s_body="${_s_body}<state>${_state}</state>"
          [ "${_state}" = "Running" ] \
              && _s_body="${_s_body}<pid>$( _get_svc_pid "${_svc}" )</pid>"
          _s_body="${_s_body}<enabled>${_enabled}</enabled>"
          _s_body="${_s_body}<monit>${_monit}</monit>"
          case "${_svc}" in
            "ssh"|"sshd")
                _root_login="$( sshd -T | grep -i -E '^permitrootlogin\s+' | awk '{print $NF}' )"
                _s_body="${_s_body}<root-login>${_root_login}</root-login>"
                ;;
            "plexmediaserver")
                if _get_plex_claim_status ; then
                    _s_body="${_s_body}<claimed>yes</claimed>"
                else
                    _s_body="${_s_body}<claimed>no</claimed>"
                fi
                ;;
          esac
          _s_body="${_s_body}</service>"
          ;;
    esac
    echo "${_s_body}"
}


_process_unattended () {
    local _body=""
    local _s_body
    local _s_body_1
    local _svc
    local _cmd
    local _svc_descr
    if [ "${FORMAT}" = "json" ] ; then
        _body="${_body}{"
        _body="${_body}\"version\":\"${_VER}\","
        _body="${_body}\"command\":\"${COMMAND}\","
        _body="${_body}\"result\":\"success\","
        _body="${_body}\"services\":["
    elif [ "${FORMAT}" = "xml" ] ; then
        _body="${_body}<?xml version=\"1.0\"?>"
        _body="${_body}<data>"
        _body="${_body}<version>${_VER}</version>"
        _body="${_body}<command>${COMMAND}</command>"
        _body="${_body}<result>success</result>"
        _body="${_body}<services>"
    else
        return
    fi

    _s_body=""
    for _svc in ${SERVICE} ; do
        case "${_svc}" in
          "all")
              for _svc_descr in ${SERVICES_LIST} ; do
                  for _cmd in ${COMMAND} ; do
                      _s_body_1="$( _process_svc_unattended "${_svc_descr}" "${_cmd}" )"
                      [ -z "${_s_body_1}" ] && continue
                      if [ "${FORMAT}" = "json" ] ; then
                          [ -n "${_s_body}" ] && _s_body="${_s_body},"
                      fi
                      _s_body="${_s_body}${_s_body_1}"
                  done
              done
              break
              ;;
          *)
              for _cmd in ${COMMAND} ; do
                  _s_body_1="$( _process_svc_unattended "${_svc}" "${_cmd}" )"
                  [ -z "${_s_body_1}" ] && continue
                  if [ -n "${_s_body}" ] ; then
                      if [ "${FORMAT}" = "json" ] ; then
                          _s_body="${_s_body},"
                      fi
                  fi
                  _s_body="${_s_body}${_s_body_1}"
              done
              ;;
        esac
    done

    if [ "${FORMAT}" = "json" ] ; then
        _body="${_body}${_s_body}]}"
    elif [ "${FORMAT}" = "xml" ] ; then
        _body="${_body}${_s_body}</services></data>"
    fi

    echo "${_body}"
}


#
# Perform cleanup and exit
#
exit_func () {
    [ "${DEBUG}" = "yes" ] && ENTRY

    # if temp files found, delete them
    [ -f "${OUTPUT}" ] && rm -vf "${OUTPUT}" >> "${LOGFILE}" 2>&1
    [ -f "${INPUT}" ] && rm -vf "${INPUT}" >> "${LOGFILE}" 2>&1
    [ -f "${DATA}" ] && rm -vf "${DATA}" >> "${LOGFILE}" 2>&1
    [ -f "${TEXT}" ] && rm -vf "${TEXT}" >> "${LOGFILE}" 2>&1

    [ "${USE_UI}" = "yes" ] && clear

    [ "${DEBUG}" = "yes" ] && RETURN
    exit ${retcode}
}


# ///////////////////////////////////////////////////////////////
# //  SCRIPT MAIN SECTION                                      //
# ///////////////////////////////////////////////////////////////

# Prepare environment
if [ -e "/etc/monit" ] ; then
    [ ! -d "/etc/monit/tmp" ] \
        && mkdir "/etc/monit/tmp"
fi

# Determine services installation status
SERVICES_LIST=""
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/apache2" ]
then
    SERVICES_LIST="${SERVICES_LIST} Apache"
fi
if [ -d "/home/${USERNAME}/.config/ariang" \
     -a -e "/etc/systemd/system/ariang@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} AriaNG"
fi
if [ -d "/home/${USERNAME}/.config/autobrr" \
     -a -e "/etc/systemd/system/autobrr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Autobrr"
fi
if [ -e "/etc/systemd/system/irssi@.service" ] ; then
    SERVICES_LIST="${SERVICES_LIST} AutoDL"
fi
if [ -d "/home/${USERNAME}/.config/bazarr" \
     -a -e "/etc/systemd/system/bazarr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Bazarr"
fi
if [ -d "/home/${USERNAME}/.config/btsync" \
     -a -e "/etc/systemd/system/btsync@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} BTsync"
fi
if [ -e "/etc/systemd/system/cherrymusic@.service" ] ; then
    SERVICES_LIST="${SERVICES_LIST} Cherrymusic"
fi
if [ -e "/home/${USERNAME}/.cloudcmd.json" \
     -a -e "/etc/systemd/system/cloudcmd@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} CloudCmd"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/etc/systemd/system/cloud-torrent@.service" \
          -a -e "/home/${USERNAME}/.config/cloud-torrent/cloud-torrent.json" ]
     then
         SERVICES_LIST="${SERVICES_LIST} CloudTorrent"
     fi
fi
if [ -e "/etc/systemd/system/couchpotato@.service" ] ; then
    SERVICES_LIST="${SERVICES_LIST} Couchpotato"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
    if [ -d "/home/${USERNAME}/.config/Cuberite" \
         -a -e "/etc/systemd/system/cuberite@.service" ]
    then
        SERVICES_LIST="${SERVICES_LIST} Cuberite"
    fi
fi
if [ -d "/home/${USERNAME}/.config/deluge" \
     -a -e "/etc/systemd/system/deluged@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} DelugeD"
fi
if [ -d "/home/${USERNAME}/.config/deluge" \
     -a -e "/etc/systemd/system/deluge-web@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} DelugeWeb"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -f "/lib/systemd/system/docker.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Docker"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/usr/lib/systemd/system/emby-server.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Emby"
fi
if [ -d "/home/${USERNAME}/.config/filebrowser" \
     -a -e "/etc/systemd/system/filebrowser@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} FileBrowser"
fi
if [ -d "/home/${USERNAME}/.config/filecommander" \
     -a -e "/etc/systemd/system/filecommander@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} FileCommander"
fi
if [ -d "/home/${USERNAME}/flood" \
     -a -e "/etc/systemd/system/flood@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Flood"
fi
if [ ${USERUID} -eq ${FIRST_UID} ]
then
    if [    -f "/etc/init.d/pure-ftpd" \
         -o -f "/usr/lib/systemd/system/pure-ftpd.service" ]
    then
        SERVICES_LIST="${SERVICES_LIST} FTPD"
    fi
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -f "/etc/systemd/system/jackett@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Jackett"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -f "/lib/systemd/system/jellyfin.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Jellyfin"
fi
if [ -d "/home/${USERNAME}/.config/lidarr" \
     -a -e "/etc/systemd/system/lidarr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Lidarr"
fi
if [ -e "/etc/ppp/chap-secrets" ] ; then
    if grep -q -e "^${USERNAME}\s*l2tpd\s*.*$" "/etc/ppp/chap-secrets" > /dev/null 2>&1 ; then
        SERVICES_LIST="${SERVICES_LIST} L2TP/IPsec"
    fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
    if [ -e "/etc/init.d/madsonic" ] ; then
        SERVICES_LIST="${SERVICES_LIST} Madsonic"
    fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
    if [    -e "/lib/systemd/system/mysql.service" \
         -o -e "/lib/systemd/system/mariadb.service" ]
    then
        SERVICES_LIST="${SERVICES_LIST} MySQL"
    fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
    if [    -d "/etc/nginx" \
         -a -e "/lib/systemd/system/nginx.service" ]
    then
        SERVICES_LIST="${SERVICES_LIST} NGINX"
    fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
    if [ -e "/lib/systemd/system/nxserver.service" \
         -o -e "/etc/init.d/nxserver" ]
    then
        SERVICES_LIST="${SERVICES_LIST} NoMachine"
    fi
fi
if [ -d "/home/${USERNAME}/.config/nzbget" \
     -a -e "/etc/systemd/system/nzbget@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} NZBGet"
elif [ -d "/home/${USERNAME}/.config/nzbgetcom" \
     -a -e "/etc/systemd/system/nzbgetcom@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} NZBGet"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/etc/systemd/system/nzbhydra2@.service" \
          -a -d "/home/${USERNAME}/.config/nzbhydra" ]
     then
         SERVICES_LIST="${SERVICES_LIST} NZBHydra2"
     fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/etc/systemd/system/ombi.service" \
          -a -d "/opt/Ombi" ]
     then
         SERVICES_LIST="${SERVICES_LIST} Ombi"
     fi
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -d "/etc/openvpn" ]
then
    SERVICES_LIST="${SERVICES_LIST} OpenVPN"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/snap.overseerr.daemon.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Overseerr"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/lib/systemd/system/plexmediaserver.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} PLEX"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/plexpy.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} PlexPy"
fi
if [ -d "/home/${USERNAME}/.config/prowlarr" \
     -a -e "/etc/systemd/system/prowlarr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Prowlarr"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -d "/opt/Proxy-Puppeteer" \
     -a -e "/etc/systemd/system/puppeteer.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Puppeteer"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/pyload.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} PyLoad"
fi
if [ -d "/home/${USERNAME}/.config/qBittorrent" \
     -a -e "/etc/systemd/system/qbittorrent@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} qBittorrent"
fi
if [ -d "/home/${USERNAME}/.config/radarr" \
     -a -e "/etc/systemd/system/radarr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Radarr"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/rclonewebui@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} RcloneWebUI"
fi
if [ -d "/home/${USERNAME}/.config/readarr" \
     -a -e "/etc/systemd/system/readarr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Readarr"
fi
if [ -d "/home/${USERNAME}/.config/resilio-sync" \
     -a -e "/etc/systemd/system/resilio-sync@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} ResilioSync"
fi
if [    -e "/etc/systemd/system/rtorrent@.service" \
     -a -e "${USERHOME}/.rtorrent.rc" ]
then
    SERVICES_LIST="${SERVICES_LIST} rTorrent"
fi
if [    -e "/etc/systemd/system/sabnzbd@.service" \
     -a -e "${USERHOME}/.sabnzbd/sabnzbd.ini" ]
then
    SERVICES_LIST="${SERVICES_LIST} SABnzbd"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/sickbeard@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Sickbeard"
fi
if [ -d "/home/${USERNAME}/.config/sickchill" \
     -a -e "/etc/systemd/system/sickchill@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} SickChill"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/sickrage@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Sickrage"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/etc/systemd/system/simple-torrent@.service" \
          -a -e "/home/${USERNAME}/.config/simple-torrent/simple-torrent.json" ]
     then
         SERVICES_LIST="${SERVICES_LIST} SimpleTorrent"
     fi
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/vpnserver.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} SoftEtherVPN"
fi
if [ -d "/home/${USERNAME}/.config/sonarr" \
     -a -e "/etc/systemd/system/sonarr@.service" ]
then
     SERVICES_LIST="${SERVICES_LIST} Sonarr"
fi
if [ -d "/home/${USERNAME}/.config/sonarr-latest" \
     -a -e "/etc/systemd/system/sonarr-latest@.service" ]
then
     SERVICES_LIST="${SERVICES_LIST} SonarrLatest"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/ssh/sshd_config" ]
then
    SERVICES_LIST="${SERVICES_LIST} SSH"
fi
if [ -x "/opt/storm/storm" \
     -a -e "/etc/systemd/system/storm@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Storm"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
    if [ -e "/etc/init.d/subsonic" ] ; then
        SERVICES_LIST="${SERVICES_LIST} Subsonic"
    fi
fi
if [ -e "/etc/systemd/system/syncthing@.service" ]
then
    if [ -e "${USERHOME}/.config/syncthing/config.xml" ] ; then
        SERVICES_LIST="${SERVICES_LIST} SyncThing"
    elif [ ${USERUID} -eq ${FIRST_UID} ] ; then
        if [ -e "/root/.config/syncthing/config.xml" ] ; then
            SERVICES_LIST="${SERVICES_LIST} SyncThing"
        fi
    fi
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -e "/etc/systemd/system/tautulli.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Tautulli"
fi
if [ ${USERUID} -eq ${FIRST_UID} \
     -a -d "/opt/thinlinc" ]
then
    if [    -e "/etc/init.d/tlwebaccess" \
         -o -e "/lib/systemd/system/tlwebaccess.service"  ]
    then
        SERVICES_LIST="${SERVICES_LIST} ThinLincWeb"
    fi
fi
if [ -d "/home/${USERNAME}/.config/transmission-daemon" \
     -a -e "/etc/systemd/system/transmission-daemon@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Transmission"
fi
if [ -d "/home/${USERNAME}/utorrent" \
     -a -e "/home/${USERNAME}/utorrent/utwhisper/utwhisper.py" \
     -a -e "/etc/systemd/system/utserver@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} uTorrent"
fi
if [ -f "/home/${USERNAME}/.vnc/passwd" \
     -a -e "/etc/systemd/system/vncserver-user.service" ]
then
    which vncpasswd > /dev/null 2>&1 && SERVICES_LIST="${SERVICES_LIST} VNC"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/etc/systemd/system/webssh.service" \
          -a -d "/opt/WebSSH2" ]
     then
         SERVICES_LIST="${SERVICES_LIST} WebSSH"
     fi
fi
if [ -d "/home/${USERNAME}/.config/whisparr" \
     -a -e "/etc/systemd/system/whisparr@.service" ]
then
    SERVICES_LIST="${SERVICES_LIST} Whisparr"
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/etc/systemd/system/rsb-wiztorrent@.service" \
          -a -d "/home/${USERNAME}/rsb-wiztorrent" ]
     then
         SERVICES_LIST="${SERVICES_LIST} WizTorrent"
     fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [    -e "/lib/systemd/system/xrdp.service" \
          -o -e "/etc/init.d/xrdp" \
          -o -e "/usr/lib/systemd/system/xrdp.service" ]
     then
         SERVICES_LIST="${SERVICES_LIST} XRDP"
     fi
fi
if [ ${USERUID} -eq ${FIRST_UID} ] ; then
     if [ -e "/etc/systemd/system/3proxy.service" ]
     then
         SERVICES_LIST="${SERVICES_LIST} 3proxy"
     fi
fi

if [ "${USE_UI}" != "yes" ] ; then
    if [ "${COMMAND}" = "list" ] ; then
        case "${FORMAT}" in
          "json")
              cat <<-EOF
		{
		"version":"${_VER}",
		"result":"success",
		"command":"list",
		"services":[
		EOF
              _line=""
              for _svc in ${SERVICES_LIST} ; do
                  [ -n "${_line}" ] && _line="${_line}, "
                  _svc_l="$( echo "${_svc}" | tr '[:upper:]' '[:lower:]' )"
                  _line="${_line}\"${_svc_l}\""
              done
              cat <<-EOF
		${_line} ] }
		EOF
              ;;
          "xml")
              cat <<-EOF
		<?xml version="1.0"?>
		<data>
		<version>${_VER}</version>
		<result>success</result>
		<command>list</command>
		EOF
              _line=""
              for _svc in ${SERVICES_LIST} ; do
                  _svc_l="$( echo "${_svc}" | tr '[:upper:]' '[:lower:]' )"
                  _line="${_line}<service name=\"${_svc_l}\"/>"
              done
              cat <<-EOF
		<services>${_line}</services>
		</data>
		EOF
              ;;
        esac
    else
        _process_unattended
    fi
    exit_func
fi




# ----------------------------
# Set infinite loop
# ----------------------------
default_item=""
while true ; do

    _dialog_infobox \
       "    Please wait...    " \
       "" \
       "\n  Retrieving installed services information...  \n\n"

    # Menu array
    ar=()
    for _svc in ${SERVICES_LIST} ; do
        [ "${DEBUG}" = "yes" ] \
            && DEBUG "Adding item: [${_svc}]"
        ar+=("${_svc}" "| $( _get_svc_status "${_svc}" )" "\Zb\Z3$( _get_svc_help "${_svc}" )\Zn")
    done

    # Count additional menu lines
    num="${#ar[@]}"
    num="$(( num / 3 ))"
    menu_h=0
    [ ${num} -gt "$(( max_lines - 7 ))" ] && menu_h="$(( max_lines - 7 ))"

    ### display main menu ###
    #    --begin 2 1 \
    #    --hline "<<< hline >>>" \
    dialog ${DIALOG_OPTS} --backtitle "$( _backtitle "${APP_TITLE} for '${USERNAME}'" )" \
        --title " [ M A I N - M E N U ] " \
        --cancel-label "Exit" \
        --default-item "${default_item}" \
        --item-help \
        --menu "You can use the UP/DOWN arrow keys, the first \n\
letter of the choice as a hot key. \n\
Choose the TASK" \
        0 0 "${menu_h}" \
        "${ar[@]}" \
                2> "${INPUT}"
    ret=$?
    [ ${ret} -eq ${DIALOG_CANCEL} -o ${ret} -eq ${DIALOG_ESC} ] && break
    menuitem=$(<"${INPUT}")
    default_item="${menuitem}"

    _menu_svc "${menuitem}"

done

exit_func
