Advert Manager CLI

Description:
Broadcast a random advert to your entire Ark Cluster.
List, Add, Delete or Send your adverts with ease.

Using Task Scheduler(windows) or a cron job(linux) easily schedule a broadcast at regular
intervals (eg: every 60 mins)

Usage:
 advert <command> [arguments]

Commands:
 list,   -ls          List all adverts
 add,    -a  <text>   Add a new advert
 del,    -d  <id>     Delete an advert
 chat,   -ch          Broadcast a random advert to all servers
 help,   -h           Show this help

Examples:
 advert list
 advert add “Join our Discord: https://discord.gg/fYZqNQVqhA”
 advert -a “Vote daily at ScruffyPVE.DuckDNS.org”
 advert del 3
 advert chat

Download advert.sh

#!/bin/bash
#
#

######################
# SERVER CONFIGURATION
#######################
HOST="YOUR-CLUSTER-IP"
RconPass="YOUR-RCON-PASS"

MCRCON="/c/mcrcon/mcrcon.exe"
DATA_FILE="/c/ark/adverts/advert.csv"
DELIM="%"

################
# SERVER ARRAYS
#################
declare -A PORTS=(
    [isl]=1234
    [rag]=1234
    [abe]=1234
    [ext]=1234
    [ast]=1234
    [gen]=1234
)
declare -A PASSWORDS=(
    [isl]="$RconPass"
    [rag]="$RconPass"
    [abe]="$RconPass"
    [ext]="$RconPass"
    [ast]="$RconPass"
    [gen]="$RconPass"
)
servers=$(printf "%s | " "${!PORTS[@]}")
servers=${servers% | } # Remove the trailing " | "

#
# END CONFIGURATION
#

VERSION="Odi's Advert Manager 1.4"

####################
# COLOUR VARIABLES
####################

# Terminal Formatting
RESET="\033[0m"
BOLD="\033[1m"

# UI Colours
CLR_RED="\033[38;5;196m"  # Bright Red
CLR_GREEN="\033[38;5;46m" # Bright Lime Green

CLR_GOLD="\033[38;5;226m"   # Gold
CLR_PURPLE="\033[38;5;141m" # Light Purple / Lavender
CLR_BLUE="\033[38;5;4m"     # Bright Sky Blue
CLR_ORANGE="\033[38;5;208m" # Orange
CLR_AQUA="\033[38;5;51m"    # Aqua
CLR_PINK="\033[38;5;199m"   # PINK
CLR_PBLUEE="\033[38;5;147m" # Pale Blue
CLR_DGREEN="\033[38;5;2m"   # Dark Forest Green
CLR_PAQUA="\033[38;5;195m"  # Pale Aqua
CLR_GREY="\033[38;5;245m"   # Darker Grey
CLR_TEXT="\033[38;5;252m"   # Light Grey
CLR_FRAME="\033[38;5;245m"  # Darker Grey

set -e

#######################
# Unicode box Chars
########################
H="─"
V="│"

TL="┌"
TR="┐"
BL="└"
BR="┘"

LT="├"
RT="┤"
TT="┬"
BT="┴"
CR="┼"

TH_FRAME="${CLR_FRAME}${TL}────${TT}────────────────────────────────────────────────────────────────────────────────────────────────────────────${TR}${RESET}"
MD_FRAME="${CLR_FRAME}${LT}────${CR}────────────────────────────────────────────────────────────────────────────────────────────────────────────${RT}${RESET}"
BH_FRAME="${CLR_FRAME}${BL}────${BT}────────────────────────────────────────────────────────────────────────────────────────────────────────────${BR}${RESET}"

ROW_PREFIX="${CLR_FRAME}${V}${RESET}"

####################
# FUNCTIONS
####################

usage() {
    echo -e "${BOLD}${VERSION}${RESET}"
    echo
    echo -e "${BOLD}Description:${RESET}"
    echo -e "${CLR_TEXT}  Manage and broadcast random server adverts to your entire Ark Cluster.${RESET}"
    echo
    echo -e "${BOLD}Usage:${RESET}"
    echo -e "  ${CLR_TEXT}advert <command> [arguments]${RESET}"
    echo

    echo -e "${BOLD}Commands:${RESET}"
    echo -e "${CLR_TEXT}  list,   -ls          List all adverts"
    echo -e "  add,    -a  <text>   Add a new advert"
    echo -e "  del,    -d  <id>     Delete an advert"
    echo -e "  chat,   -ch          Broadcast a random advert to all servers"
    echo -e "  help,   -h           Show this help${RESET}"
    echo

    echo -e "${BOLD}Examples:${RESET}"
    echo -e "${CLR_TEXT}  advert list"
    echo -e "  advert add \"Join our Discord: https://discord.gg/fYZqNQVqhA\""
    echo -e "  advert -a \"Vote daily at ScruffyPVE.DuckDNS.org\""
    echo -e "  advert del 3"
    echo -e "  advert chat${RESET}"
    echo
}

error() {
    echo
    echo -e "  ${CLR_RED}Error: ${RESET}$1"
    echo
}

advert_action() {
    echo
    echo "────────────────────────"
    echo -e " ▶ ${1}Advert (${RESET}${BOLD}${2}${RESET}${1}) ${3}${RESET}"
    echo "────────────────────────"
}

next_id() {

    if [[ ! -s "$DATA_FILE" ]]; then
        echo 1
        return
    fi

    awk -F'%' '
        $1 > max { max = $1 }
        END { print max + 1 }
    ' "$DATA_FILE"
}

send_rcon() {
    local server="$1"
    shift
    local command="$*"
    local result

    result=$(
        "$MCRCON" \
            -H "$HOST" \
            -P "${PORTS[$server]}" \
            -p "${PASSWORDS[$server]}" \
            "$command" 2>&1 |
            sed -E 's/\x1B\[[0-9;]*[[:alpha:]]//g'
    )

    printf '%s\n' "$result"
}

cmd_list() {

    [[ -f "$DATA_FILE" ]] || touch "$DATA_FILE"

    local FMT="$ROW_PREFIX %2b $ROW_PREFIX %-121b $ROW_PREFIX\n"

    echo
    echo -e "${TH_FRAME}"

    printf "$FMT" "${CLR_ORANGE}ID${RESET}" "${CLR_ORANGE}ADVERTISEMENT${RESET}"
    printf "%b" "$RESET"
    echo -e "${MD_FRAME}"

    if [[ ! -s "$DATA_FILE" ]]; then
        echo " No adverts"
        echo -e "${BH_FRAME}"
        echo
        return
    fi

    local first=1

    while IFS="$DELIM" read -r id advert; do

        ((first)) || echo -e "${MD_FRAME}"
        first=0

        printf "$ROW_PREFIX ${CLR_GOLD}%2b${RESET} $ROW_PREFIX %s \n" \
            "$id" "$advert"

    done <"$DATA_FILE"

    echo -e "${BH_FRAME}"
    echo
}

cmd_add() {
    local id advert
    id=$(next_id)
    advert="$*"

    echo "${id}${DELIM}${advert}" >>"$DATA_FILE"

    advert_action "${CLR_GREEN}" "$id" "Created"
}

cmd_delete() {
    local delete_id="$1"

    #
    # Ensure the ID is numerical & Exists
    #

    # If Blank
    if [[ -z "$delete_id" ]]; then
        error "No Ticket ID Specified"
        echo "  Usage: advert -d <id>"
        echo
        return 1
    fi

    # IF input isn't a number
    if [[ ! $delete_id =~ ^[0-9]+$ ]]; then
        error "${delete_id} is not a numerical value"
        exit
    fi

    # If delete_id is 5, this searches specifically for "^5%"
    # to ensure the delete_id exists in $DATA_FILE
    if grep -q "^${delete_id}${DELIM}" "$DATA_FILE"; then

        #
        # Finish checks - continue Deleting
        #

        while IFS="$DELIM" read -r id advert; do
            [[ "$id" == "$delete_id" ]] && continue
            echo "${id}${DELIM}${advert}"
        done <"$DATA_FILE" >"$DATA_FILE.tmp"

        mv "$DATA_FILE.tmp" "$DATA_FILE"

        advert_action "${CLR_RED}" "$delete_id" "Deleted"

    else
        error "Advert '$delete_id' does not exist."
    fi
}

cmd_chatall() {

    [[ -s "$DATA_FILE" ]] || {
        error "No adverts available."
        exit 1
    }

    # Pick a random advert
    local line id message chstatus

    line=$(shuf -n1 "$DATA_FILE")
    id="${line%%${DELIM}*}"
    message="${line#*${DELIM}}"

    echo
    echo -e "${CLR_AQUA} ▶ Sending Advert #${id} to all servers${RESET}"
    echo
    echo "────────────────────────"
    echo -e "${CLR_GOLD} $message ${RESET}"
    echo "────────────────────────"
    echo

    for servername in "${!PORTS[@]}"; do
        echo -e "${CLR_PURPLE}${servername^^}${RESET}"

        chstatus=$(send_rcon "$servername" serverchat "$message")

        if [[ "$chstatus" == *"Server received, But no response!!"* ]]; then
            echo "▶ Advert Delivered"
        else
            echo "$chstatus"
        fi
        echo
    done

    echo "────────────────────────"
    echo
}

####################
# COMMANDS
####################
case "${1:-}" in
    list | -ls)
        cmd_list
        ;;
    add | -a)
        shift
        cmd_add "$@"
        ;;
    delete | del | -d)
        shift
        cmd_delete "$1"
        ;;
    chat | -ch)
        cmd_chatall
        exit 0
        ;;
    help | -h)
        usage
        ;;
    *)
        usage
        exit 1
        ;;
esac