diff --git a/resources/moonraker-telegram-bot.service b/resources/moonraker-telegram-bot.service new file mode 100644 index 0000000..fd0ce2a --- /dev/null +++ b/resources/moonraker-telegram-bot.service @@ -0,0 +1,18 @@ +#Systemd service file for Moonraker Telegram Bot + +[Unit] +Description=Starts Moonraker Telegram Bot instance %INST% on startup +Documentation=https://github.com/nlef/moonraker-telegram-bot/wiki +After=network.target + +[Install] +WantedBy=multi-user.target + +[Service] +Environment=TELEGRAM_CONF=%CFG% +Type=simple +User=%USER% +RemainAfterExit=yes +ExecStart=%ENV%/bin/python %DIR%/bot/main.py -c ${TELEGRAM_CONF} +Restart=always +RestartSec=10 \ No newline at end of file diff --git a/scripts/moonraker-telegram-bot.sh b/scripts/moonraker-telegram-bot.sh index b13d059..b72e151 100644 --- a/scripts/moonraker-telegram-bot.sh +++ b/scripts/moonraker-telegram-bot.sh @@ -21,26 +21,256 @@ function telegram_bot_systemd() { echo "${services}" } -function install_telegram_bot(){ - telegram_bot_setup - do_action_service "restart" "moonraker-telegram-bot" +function telegram_bot_setup_dialog(){ + status_msg "Initializing Telegram Bot installation ..." + + ### return early if moonraker is not installed + local moonraker_services + moonraker_services=$(moonraker_systemd) + if [[ -z "${moonraker_services}" ]]; then + local error="Moonraker not installed! Please install Moonraker first!" + log_error "Telegram Bot setup started without Moonraker being installed. Aborting setup." + print_error "${error}" && return + fi + + local moonraker_count user_input=() moonraker_names=() + moonraker_count=$(echo "${moonraker_services}" | wc -w ) + for service in ${moonraker_services}; do + moonraker_names+=( "$(get_instance_name "${service}")" ) + done + + local telegram_bot_count + if (( moonraker_count == 1 )); then + ok_msg "Moonraker installation found!\n" + telegram_bot_count=1 + elif (( moonraker_count > 1 )); then + top_border + printf "|${green}%-55s${white}|\n" " ${moonraker_count} Moonraker instances found!" + for name in "${moonraker_names[@]}"; do + printf "|${cyan}%-57s${white}|\n" " ● ${name}" + done + blank_line + echo -e "| The setup will apply the same names to Telegram Bot! |" + blank_line + echo -e "| Please select the number of Telegram Bot instances to |" + echo -e "| install. Usually one Telegram Bot instance per |" + echo -e "| Moonraker instance is required but you may not |" + echo -e "| install more Telegram Bot instances than available |" + echo -e "| Moonraker instances. |" + bottom_border + + ### ask for amount of instances + local re="^[1-9][0-9]*$" + while ! [[ ${telegram_bot_count} =~ ${re} && ${telegram_bot_count} -le ${moonraker_count} ]]; do + read -p "${cyan}###### Number of Telegram Bot instances to set up:${white} " -i "${moonraker_count}" -e telegram_bot_count + ### break if input is valid + [[ ${telegram_bot_count} =~ ${re} && ${telegram_bot_count} -le ${moonraker_count} ]] && break + ### conditional error messages + error_msg "Invalid input:" + ! [[ ${telegram_bot_count} =~ ${re} ]] && error_msg "● Input not a number" + ((telegram_bot_count > moonraker_count)) && error_msg "● Number of Telegram Bot instances larger than existing Moonraker instances" + done && select_msg "${telegram_bot_count}" + else + log_error "Internal error. moonraker_count of '${moonraker_count}' not equal or grather than one!" + return 1 + fi + + user_input+=("${telegram_bot_count}") + +### confirm instance amount + while true; do + ((telegram_bot_count == 1)) && local question="Install Telegram Bot?" + ((telegram_bot_count > 1)) && local question="Install ${telegram_bot_count} Telegram Bot instances?" + read -p "${cyan}###### ${question} (Y/n):${white} " yn + case "${yn}" in + Y|y|Yes|yes|"") + select_msg "Yes" + break;; + N|n|No|no) + select_msg "No" + abort_msg "Exiting Telegram Bot setup ...\n" + return;; + *) + error_msg "Invalid Input!";; + esac + done + + ### write existing klipper names into user_input array to use them as names for moonraker + if (( moonraker_count > 1 )); then + for name in "${moonraker_names[@]}"; do + user_input+=("${name}") + done + fi + + ((telegram_bot_count > 1)) && status_msg "Installing ${telegram_bot_count} Telegram Bot instances ..." + ((telegram_bot_count == 1)) && status_msg "Installing Telegram Bot ..." + telegram_bot_setup "${user_input[@]}" +} + +function install_telegram_bot_dependencies(){ + local packages + local install_script="${MOONRAKER_TELEGRAM_BOT_DIR}/scripts/install.sh" + + ### read PKGLIST from official install script + status_msg "Reading dependencies..." + # shellcheck disable=SC2016 + packages="$(grep "PKGLIST=" "${install_script}" | cut -d'"' -f2 | sed 's/\${PKGLIST}//g' | tr -d '\n')" + + echo "${cyan}${packages}${white}" | tr '[:space:]' '\n' + read -r -a packages <<< "${packages}" + + ### Update system package info + status_msg "Updating lists of packages..." + sudo apt-get update --allow-releaseinfo-change + + ### Install required packages + status_msg "Installing packages..." + sudo apt-get install --yes "${packages[@]}" +} + +function create_telegram_bot_virtualenv(){ + status_msg "Installing python virtual environment..." + ### always create a clean virtualenv + [[ -d ${MOONRAKER_TELEGRAM_BOT_ENV_DIR} ]] && rm -rf "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}" + virtualenv -p /usr/bin/python3 --system-site-packages "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}" + "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}"/bin/pip install -r "${MOONRAKER_TELEGRAM_BOT_DIR}/scripts/requirements.txt" } function telegram_bot_setup(){ - local klipper_cfg_loc - klipper_cfg_loc="$(get_klipper_cfg_dir)" - export klipper_cfg_loc - local dep=(virtualenv) + local instance_arr=("${@}") + ### checking dependencies + local dep=(git virtualenv) dependency_check "${dep[@]}" + + ### step 1: clone telegram bot status_msg "Downloading Moonraker-Telegram-Bot ..." - #force remove existing Moonraker-Telegram-Bot dir - [ -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ] && rm -rf "${MOONRAKER_TELEGRAM_BOT_DIR}" - #clone into fresh Moonraker-Telegram-Bot dir + ### force remove existing Moonraker-Telegram-Bot dir + [[ -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ]] && rm -rf "${MOONRAKER_TELEGRAM_BOT_DIR}" cd "${HOME}" && git clone "${MOONRAKER_TELEGRAM_BOT_REPO}" - ok_msg "Download complete!" - status_msg "Installing Moonraker-Telegram-Bot ..." - /bin/bash "${MOONRAKER_TELEGRAM_BOT_DIR}/scripts/install.sh" - echo; ok_msg "Moonraker-Telegram-Bot successfully installed!" + + ### step 2: install telegram bot dependencies and create python virtualenv + status_msg "Installing dependencies ..." + install_telegram_bot_dependencies + create_telegram_bot_virtualenv + + ### step 3: create telegram.conf + create_telegram_conf "${instance_arr[@]}" + + ### step 4: create telegram bot instances + create_telegram_bot_service "${instance_arr[@]}" + + ### step 5: enable and start all instances + do_action_service "enable" "moonraker-telegram-bot" + do_action_service "start" "moonraker-telegram-bot" + + ### confirm message + local confirm="" + (( instance_arr[0] == 1)) && confirm="Telegram Bot has been set up!" + (( instance_arr[0] > 1)) && confirm="${instance_arr[0]} Telegram Bot instances have been set up!" + print_confirm "${confirm}" && return +} + +function create_telegram_conf(){ + local input=("${@}") + local telegram_bot_count=${input[0]} && unset "input[0]" + local names=("${input[@]}") && unset "input[@]" + local log="${KLIPPER_LOGS}" + + if (( telegram_bot_count == 1 )); then + cfg_dir="${KLIPPER_CONFIG}" + cfg="${cfg_dir}/telegram.conf" + ### write single instance config + write_telegram_conf "${cfg_dir}" "${cfg}" "${log}" + + elif (( telegram_bot_count > 1 )); then + local j=0 re="^[1-9][0-9]*$" + + for ((i=1; i <= telegram_bot_count; i++ )); do + ### overwrite config folder if name is only a number + if [[ ${names[j]} =~ ${re} ]]; then + cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" + else + cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" + fi + + ### write multi instance config + write_telegram_conf "${cfg_dir}" "${cfg}" "${log}" + port=$((port+1)) + j=$((j+1)) + done && unset j + + else + return 1 + fi +} + +function write_telegram_conf(){ + local cfg_dir=${1} cfg=${2} log=${3} + local conf_template="${MOONRAKER_TELEGRAM_BOT_DIR}/scripts/base_install_template" + ! [[ -d "${cfg_dir}" ]] && mkdir -p "${cfg_dir}" + + if ! [[ -f "${cfg}" ]]; then + status_msg "Creating telegram.conf in ${cfg_dir} ..." + cp "${conf_template}" "${cfg}" + sed -i "s|some_log_path|${log}|g" "${cfg}" + ok_msg "telegram.conf created!" + else + status_msg "File '${cfg}' already exists!\nSkipping..." + fi +} + +function create_telegram_bot_service(){ + local input=("${@}") + local instances=${input[0]} && unset "input[0]" + local names=("${input[@]}") && unset "input[@]" + local cfg_dir cfg service + if (( instances == 1 )); then + cfg_dir="${KLIPPER_CONFIG}" + cfg="${cfg_dir}/telegram.conf" + service="${SYSTEMD}/moonraker-telegram-bot.service" + ### write single instance service + write_telegram_bot_service "" "${cfg}" "${service}" + ok_msg "Single Telegram Bot instance created!" + + elif (( instances > 1 )); then + local j=0 re="^[1-9][0-9]*$" + + for ((i=1; i <= instances; i++ )); do + + ### overwrite config folder if name is only a number + if [[ ${names[j]} =~ ${re} ]]; then + cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" + else + cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" + fi + + cfg="${cfg_dir}/telegram.conf" + service="${SYSTEMD}/moonraker-telegram-bot-${names[${j}]}.service" + ### write multi instance service + write_telegram_bot_service "${i}(${names[${j}]})" "${cfg}" "${service}" + ok_msg "Telegram Bot instance #${i}(${names[${j}]}) created!" + j=$((j+1)) + + done && unset j + + else + return 1 + fi +} + +function write_telegram_bot_service(){ + local i=${1} cfg=${2} service=${3} + local service_template="${SRCDIR}/kiauh/resources/moonraker-telegram-bot.service" + + ### replace all placeholders + if ! [[ -f "${service}" ]]; then + status_msg "Creating Telegram Bot Service ${i} ..." + sudo cp "${service_template}" "${service}" + [[ -z ${i} ]] && sudo sed -i "s|instance %INST% ||" "${service}" + [[ -n ${i} ]] && sudo sed -i "s|%INST%|${i}|" "${service}" + sudo sed -i "s|%USER%|${USER}|; s|%ENV%|${MOONRAKER_TELEGRAM_BOT_ENV_DIR}|; s|%DIR%|${MOONRAKER_TELEGRAM_BOT_DIR}|" "${service}" + sudo sed -i "s|%CFG%|${cfg}|" "${service}" + fi } @@ -48,44 +278,52 @@ function telegram_bot_setup(){ #=========== REMOVE MOONRAKERTELEGRAMBOT ===========# #===================================================# -function remove_telegram_bot(){ - ### remove Moonraker-Telegram-Bot dir - if [ -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ]; then - status_msg "Removing Moonraker-Telegram-Bot directory ..." - rm -rf "${MOONRAKER_TELEGRAM_BOT_DIR}" && ok_msg "Directory removed!" - fi +function remove_telegram_bot_systemd() { + [[ -z "$(telegram_bot_systemd)" ]] && return + status_msg "Removing Telegram Bot Systemd Services ..." + for service in $(telegram_bot_systemd | cut -d"/" -f5); do + status_msg "Removing ${service} ..." + sudo systemctl stop "${service}" + sudo systemctl disable "${service}" + sudo rm -f "${SYSTEMD}/${service}" + ok_msg "Done!" + done + ### reloading units + sudo systemctl daemon-reload + sudo systemctl reset-failed + ok_msg "Telegram Bot Services removed!" +} - ### remove Moonraker-Telegram-Bot VENV dir - if [ -d "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}" ]; then - status_msg "Removing Moonraker-Telegram-Bot VENV directory ..." - rm -rf "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}" && ok_msg "Directory removed!" - fi +function remove_telegram_bot_dir() { + ! [[ -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ]] && return + status_msg "Removing Moonraker-Telegram-Bot directory ..." + rm -rf "${MOONRAKER_TELEGRAM_BOT_DIR}" + ok_msg "Directory removed!" +} - ### remove Moonraker-Telegram-Bot service - if [ -e "${SYSTEMD}/moonraker-telegram-bot.service" ]; then - status_msg "Removing Moonraker-Telegram-Bot service ..." - do_action_service "stop" "moonraker-telegram-bot" - do_action_service "disable" "moonraker-telegram-bot" - sudo rm -f "${SYSTEMD}/moonraker-telegram-bot.service" - ###reloading units - sudo systemctl daemon-reload - sudo systemctl reset-failed - ok_msg "Moonraker-Telegram-Bot Service removed!" - fi +function remove_telegram_bot_env() { + ! [[ -d "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}" ]] && return + status_msg "Removing moonraker-telegram-bot-env directory ..." + rm -rf "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}" + ok_msg "Directory removed!" +} - ### remove Moonraker-Telegram-Bot log - if [ -e "/tmp/telegram.log" ] || [ -e "${HOME}/klipper_logs/telegram.log" ]; then +function remove_telegram_bot_logs() { + if [[ -f "/tmp/telegram.log"|| -f "${HOME}/klipper_logs/telegram.log" ]]; then status_msg "Removing Moonraker-Telegram-Bot log file ..." - rm -f "/tmp/telegram.log" "${HOME}/klipper_logs/telegram.log" && ok_msg "File removed!" + rm -f "/tmp/telegram.log" "${HOME}/klipper_logs/telegram.log" + ok_msg "File removed!" fi +} - ### remove Moonraker-Telegram-Bot log symlink in config dir - if [ -e "${KLIPPER_CONFIG}/telegram.log" ]; then - status_msg "Removing Moonraker-Telegram-Bot log symlink ..." - rm -f "${KLIPPER_CONFIG}/telegram.log" && ok_msg "File removed!" - fi +function remove_telegram_bot(){ + remove_telegram_bot_systemd + remove_telegram_bot_dir + remove_telegram_bot_env + remove_telegram_bot_logs - print_confirm "Moonraker-Telegram-Bot successfully removed!" + local confirm="Moonraker-Telegram-Bot was successfully removed!" + print_confirm "${confirm}" && return } #===================================================# @@ -93,13 +331,21 @@ function remove_telegram_bot(){ #===================================================# function update_telegram_bot(){ - local klipper_cfg_loc - klipper_cfg_loc="$(get_klipper_cfg_dir)" do_action_service "stop" "moonraker-telegram-bot" - cd "${MOONRAKER_TELEGRAM_BOT_DIR}" && git pull - /bin/bash "./scripts/install.sh" - do_action_service "start" "moonraker-telegram-bot" + if ! [[ -d ${MOONRAKER_TELEGRAM_BOT_DIR} ]]; then + cd "${HOME}" && git clone "${MOONRAKER_TELEGRAM_BOT_REPO}" + else + backup_before_update "moonraker-telegram-bot" + status_msg "Updating Moonraker ..." + cd "${MOONRAKER_TELEGRAM_BOT_DIR}" && git pull + ### read PKGLIST and install possible new dependencies + install_telegram_bot_dependencies + ### install possible new python dependencies + "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}"/bin/pip install -r "${MOONRAKER_TELEGRAM_BOT_DIR}/scripts/requirements.txt" + fi + ok_msg "Update complete!" + do_action_service "start" "moonraker-telegram-bot" } #===================================================# @@ -112,16 +358,16 @@ function get_telegram_bot_status(){ ### remove the "SERVICE" entry from the data array if a moonraker service is installed local data_arr=(SERVICE "${MOONRAKER_TELEGRAM_BOT_DIR}" "${MOONRAKER_TELEGRAM_BOT_ENV_DIR}") - [ "${sf_count}" -gt 0 ] && unset "data_arr[0]" + ((sf_count > 0)) && unset "data_arr[0]" ### count+1 for each found data-item from array local filecount=0 for data in "${data_arr[@]}"; do - [ -e "${data}" ] && filecount=$(("${filecount}" + 1)) + [[ -e ${data} ]] && filecount=$((filecount + 1)) done - if (( filecount == ${#data_arr[*]})); then - status="Installed!" + if ((filecount == ${#data_arr[*]})); then + status="Installed: ${sf_count}" elif ((filecount == 0)); then status="Not installed!" else @@ -132,7 +378,7 @@ function get_telegram_bot_status(){ function get_local_telegram_bot_commit(){ local commit - [ ! -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ] || [ ! -d "${MOONRAKER_TELEGRAM_BOT_DIR}"/.git ] && return + ! [[ -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ]] || ! [[ -d "${MOONRAKER_TELEGRAM_BOT_DIR}"/.git ]] && return cd "${MOONRAKER_TELEGRAM_BOT_DIR}" commit="$(git describe HEAD --always --tags | cut -d "-" -f 1,2)" echo "${commit}" @@ -140,7 +386,7 @@ function get_local_telegram_bot_commit(){ function get_remote_telegram_bot_commit(){ local commit - [ ! -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ] || [ ! -d "${MOONRAKER_TELEGRAM_BOT_DIR}"/.git ] && return + ! [[ -d "${MOONRAKER_TELEGRAM_BOT_DIR}" ]] || ! [[ -d "${MOONRAKER_TELEGRAM_BOT_DIR}"/.git ]] && return cd "${MOONRAKER_TELEGRAM_BOT_DIR}" && git fetch origin -q commit=$(git describe origin/master --always --tags | cut -d "-" -f 1,2) echo "${commit}" @@ -151,7 +397,7 @@ function compare_telegram_bot_versions(){ local versions local_ver remote_ver local_ver="$(get_local_telegram_bot_commit)" remote_ver="$(get_remote_telegram_bot_commit)" - if [ "${local_ver}" != "${remote_ver}" ]; then + if [[ "${local_ver}" != "${remote_ver}" ]]; then versions="${yellow}$(printf " %-14s" "${local_ver}")${white}" versions+="|${green}$(printf " %-13s" "${remote_ver}")${white}" # add moonraker-telegram-bot to the update all array for the update all function in the updater diff --git a/scripts/ui/install_menu.sh b/scripts/ui/install_menu.sh index 0cdb4de..21e5560 100755 --- a/scripts/ui/install_menu.sh +++ b/scripts/ui/install_menu.sh @@ -54,7 +54,7 @@ function install_menu(){ 7) do_action "install_pgc_for_klipper" "install_ui";; 8) - do_action "install_telegram_bot" "install_ui";; + do_action "telegram_bot_setup_dialog" "install_ui";; 9) do_action "install_mjpg-streamer" "install_ui";; B|b)