From 64403c284b9515d41aae11ee314071356d687d2f Mon Sep 17 00:00:00 2001 From: Rob Frawley 2nd <rmf@src.run> Date: Mon, 6 Mar 2023 07:46:49 -0500 Subject: [PATCH] 2023 --- .gitignore | 1 + .gitmodules | 6 + LICENSE.md | 0 README.md | 0 bin-available/blocklist-dl.bash | 143 ++++++- bin-available/call-in-zsh-environment.zsh | 45 +++ bin-available/colors.bash | 80 ++++ bin-available/composer-download-global.bash | 117 ++++++ .../{bash.bash => ip-public-enp7s0.bash} | 5 +- bin-available/ip-public-tun0.bash | 2 +- bin-available/magnet-queue.bash | 61 +-- bin-available/magnet-queue.bash.bk | 173 +++++++++ bin-available/magnet-to-torrent-watcher.bash | 37 +- bin-available/mague-args.bash | 292 ++++++++++++++ bin-available/mague-file.bash | 49 +++ bin-available/monitor-torrent-watcher.bash | 23 ++ bin-available/start-glances.bash | 2 +- bin-available/start-openvpn.bash | 96 +++++ bin-available/start-rtorrent.bash | 171 ++++++++ bin-available/start-screen-recorder.bash | 0 bin-available/start-serferals.bash | 100 +++++ bin-available/start-serferals2.bash | 201 ++++++++++ bin-enabled/blocklist-dl~ | 240 ++++++++++++ bin-enabled/composer-download-global | 1 + bin-enabled/ip-public-enp7s0 | 1 + bin-enabled/magnet-to-torrent-writer | 139 ++++++- bin-enabled/mague-args | 1 + bin-enabled/mague-file | 1 + bin-enabled/monitor-torrent-watcher | 1 + bin-enabled/mqueue-args | 2 +- bin-enabled/mqueue-file | 2 +- bin-enabled/start-openvpn | 1 + bin-enabled/start-rtorrent | 1 + bin-enabled/start-speedometer | 8 + bin-enabled/watch-openvpn | 1 + lib/bashlink | 1 + lib/bright-library | 2 +- lib/rebash | 1 + lib/resrc/setup.bash | 285 ++++++++++++++ mod/logger/logger.bash | 367 ++++++++++++++++++ 40 files changed, 2574 insertions(+), 85 deletions(-) create mode 100644 .gitignore mode change 100644 => 100755 .gitmodules mode change 100644 => 100755 LICENSE.md mode change 100644 => 100755 README.md create mode 100755 bin-available/call-in-zsh-environment.zsh create mode 100755 bin-available/colors.bash create mode 100755 bin-available/composer-download-global.bash rename bin-available/{bash.bash => ip-public-enp7s0.bash} (62%) mode change 100644 => 100755 create mode 100755 bin-available/magnet-queue.bash.bk create mode 100755 bin-available/mague-args.bash create mode 100755 bin-available/mague-file.bash create mode 100755 bin-available/monitor-torrent-watcher.bash create mode 100755 bin-available/start-openvpn.bash create mode 100755 bin-available/start-rtorrent.bash mode change 100644 => 100755 bin-available/start-screen-recorder.bash create mode 100755 bin-available/start-serferals.bash create mode 100755 bin-available/start-serferals2.bash create mode 100755 bin-enabled/blocklist-dl~ create mode 120000 bin-enabled/composer-download-global create mode 120000 bin-enabled/ip-public-enp7s0 mode change 120000 => 100755 bin-enabled/magnet-to-torrent-writer create mode 120000 bin-enabled/mague-args create mode 120000 bin-enabled/mague-file create mode 120000 bin-enabled/monitor-torrent-watcher create mode 120000 bin-enabled/start-openvpn create mode 120000 bin-enabled/start-rtorrent create mode 100755 bin-enabled/start-speedometer create mode 120000 bin-enabled/watch-openvpn create mode 160000 lib/bashlink create mode 160000 lib/rebash create mode 100755 lib/resrc/setup.bash create mode 100755 mod/logger/logger.bash diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a44989 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.save diff --git a/.gitmodules b/.gitmodules old mode 100644 new mode 100755 index 3e98a58..a173dd0 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "lib/krakenx"] path = lib/krakenx url = https://github.com/KsenijaS/krakenx.git +[submodule "lib/rebash"] + path = lib/rebash + url = https://github.com/jandob/rebash.git +[submodule "lib/bashlink"] + path = lib/bashlink + url = https://github.com/thaibault/bashlink.git diff --git a/LICENSE.md b/LICENSE.md old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/bin-available/blocklist-dl.bash b/bin-available/blocklist-dl.bash index e7e1711..7167715 100755 --- a/bin-available/blocklist-dl.bash +++ b/bin-available/blocklist-dl.bash @@ -13,11 +13,12 @@ # configuration variables # -BLOCKLIST_URL="http://list.iblocklist.com/?list=bt_level2&fileformat=cidr&archiveformat=gz" -BLOCKLIST_EXT_TYPE="cidr" -BLOCKLIST_OUT_ROOT="/tmp" -BLOCKLIST_LOG_ROOT="/tmp" -BLOCKLIST_TMP_ROOT="/tmp" +BLOCKLIST_URL_LINK='http://list.iblocklist.com/?list=bt_level2&fileformat=cidr&archiveformat=gz' +BLOCKLIST_EXT_TYPE='cidr' +BLOCKLIST_DIR_BASE='/pool/torrent/blocklist-comprehensive' +BLOCKLIST_OUT_ROOT="${BLOCKLIST_DIR_BASE}/src" +BLOCKLIST_LOG_ROOT="${BLOCKLIST_DIR_BASE}/var" +BLOCKLIST_TMP_ROOT="${BLOCKLIST_DIR_BASE}/tmp" # # internal variables @@ -26,14 +27,108 @@ BLOCKLIST_TMP_ROOT="/tmp" BLOCKLIST_OUT="${BLOCKLIST_OUT_ROOT}/blocklist.${BLOCKLIST_EXT_TYPE}.txt" BLOCKLIST_LOG="${BLOCKLIST_LOG_ROOT}/blocklist.${BLOCKLIST_EXT_TYPE}.log" -function log_start() +function nuller() { - printf '\n[RUN @ "%s"]\n' "$(date)" >> "${BLOCKLIST_LOG}" + local nullable=${1:-$(</dev/stdin)} + + printf '[NULLABLE] => "%s"\n' "${nullable}" +} + +printf 'a fun little error message!' @> >(nuller) +printf 'a fun little error message!' 2>&1 1> >(nuller) +printf 'a fun little error message!' 1>&2 2> >(nuller) +exit +function fmt_date() +{ + local format="${1}" + + if [[ -n ${format} ]]; then + date +"${format}" 2> /dev/null | awk '{$1=$1};1' 2> /dev/null + + return $? + fi + + return 1 } -function out_title() +function get_date() { - local format="${1^^}" + local detail="${1:-1}" + local f_year='%Y' + local format='%m-%d' + + [[ ${detail} -eq 1 ]] && format="${f_year}:${format}" + + fmt_date "${format}" + + return $? +} + +function get_time() +{ + local detail="${1:-1}" + local format='' + + local f_h_24='%H' + local f_m_24='%M' + local f_s_24='%S' + local f_n_24='%N' + local f_p_24='' + local fmt_24="${f_h_24}:${f_m_24}" + + local f_h_12='%I' + local f_m_12='%M' + local f_s_12='%S' + local f_n_12='%N' + local f_p_12='%p' + local fmt_12="${f_h_12}:${f_m_24}" + + [[ ${detail} -eq 1 ]] && fmt_24="${fmt_24}" + [[ ${detail} -eq 2 ]] && fmt_24="${fmt_24}:${f_s_24}" + [[ ${detail} -eq 3 ]] && fmt_24="${fmt_24}:${f_s_24}.${f_n_24}" + + [[ ${detail} -eq -1 ]] && fmt_12="${fmt_12} ${f_p_12}" + [[ ${detail} -eq -2 ]] && fmt_12="${fmt_12}:${f_s_12} ${f_p_12}" + [[ ${detail} -eq -3 ]] && fmt_12="${fmt_12}:${f_s_12}.${f_n_12} ${f_p_12}" + + if [[ ${detail} -ge 0 ]]; then + format="${fmt_24}" + else + format="${fmt_12}" + fi + + fmt_date "${format}" + + return $? +} + +function get_unix() +{ + local detail="${1:-1}" + local f_nans='%N' + local format="%s" + + [[ ${detail} -eq 1 ]] && format+=".${f_nans}" + [[ ${detail} -eq -1 ]] && format="${f_nans}" + + fmt_date "${format}" + + return $? +} + +printf '[get_date ] => "%s"\n' "$(get_date)" +printf '[get_time ] => "%s"\n' "$(get_time)" +printf '[get_unix ] => "%s"\n' "$(get_unix)" +printf '[get_unix:1] => "%s"\n' "$(get_unix 1)" +printf '[get_unix:1] => "%s"\n' "$(get_unix 0)" + +exit + +#date +%Y-%m-%d\ \@\ %H:%M:%S\ \(%s\.%N\) + +function out_sect() +{ + local format=" [ ${1^^} ] " shift printf "${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" @@ -47,16 +142,22 @@ function out_info() printf " • ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" } -function out_error() +function out_warn() { local format="${1}" shift - printf " • [ERROR] ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" + printf " ! [WARN] ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" exit 255 } +function log_init() +{ + out_sect 'LOG-RUN @ "%s"' "$(date)" + printf '\n[RUN @ "%s"]\n' "$(date)" >> "${BLOCKLIST_LOG}" +} + function main() { local path="${BLOCKLIST_TMP_ROOT}/blocklist-download-temporary-work" @@ -82,15 +183,15 @@ function main() fi fi - log_start - out_title 'Updating blocklist:' "${BLOCKLIST_URL}" + log_init + out_sect 'Updating blocklist:' "${BLOCKLIST_URL_LINK}" out_info 'Logged blocklist stat: %s' "${BLOCKLIST_LOG}" if [[ ! -d "${path}" ]]; then mkdir -p "${path}" if [[ $? -ne 0 ]]; then - out_error 'Unable to create temporary working directory "%s"!' "${path}" + out_warn 'Unable to create temporary working directory "%s"!' "${path}" fi fi @@ -98,23 +199,23 @@ function main() rm "${file}" if [[ $? -ne 0 ]]; then - out_error 'Unable to remove old temporary working file "%s"!' "${file}" + out_warn 'Unable to remove old temporary working file "%s"!' "${file}" fi fi - out_info 'Fetch blocklist link: "%s"' "${BLOCKLIST_URL}" + out_info 'Fetch blocklist link: "%s"' "${BLOCKLIST_URL_LINK}" - wget -q -O "${file}" "${BLOCKLIST_URL}" + wget -q -O "${file}" "${BLOCKLIST_URL_LINK}" if [[ $? -ne 0 ]]; then - out_error 'Unable to download blocklist "%s"!' "${BLOCKLIST_URL}" + out_warn 'Unable to download blocklist "%s"!' "${BLOCKLIST_URL_LINK}" exit fi local size="$(gzip -dc "${file}" | grep -E '^[0-9]' | wc -l)" if [[ ${size} -eq 0 ]]; then - out_error 'Unable to create blocklist as download contains 0 lines!' + out_warn 'Unable to create blocklist as download contains 0 lines!' exit fi @@ -123,7 +224,7 @@ function main() gzip -dc "${file}" | grep -E '^[0-9]' | sort -u > "${BLOCKLIST_OUT}" if [[ $? -ne 0 ]]; then - out_error 'Unable to parse downloaded blocklist "%s"!' "${path}" + out_warn 'Unable to parse downloaded blocklist "%s"!' "${path}" fi out_info 'Clean temporary data: "%s"' "${path}" @@ -131,7 +232,7 @@ function main() rm -fr "${path}" if [[ $? -ne 0 ]]; then - out_error 'Unable to remove temporary working path "%s"!' "${path}" + out_warn 'Unable to remove temporary working path "%s"!' "${path}" fi } diff --git a/bin-available/call-in-zsh-environment.zsh b/bin-available/call-in-zsh-environment.zsh new file mode 100755 index 0000000..6c9c6c0 --- /dev/null +++ b/bin-available/call-in-zsh-environment.zsh @@ -0,0 +1,45 @@ +#!/bin/zsh + +## +## This file is part of the `src-run/user-scripts-server` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +printf '\n##\n## robfrawley/zsh-env\n## Wrapper script to ensure ZSH environment is properly loaded for the command being called.\n##\n\n' + +if [[ -z "${ZSH}" ]] && [[ -r "${HOME}/.zshrc" ]]; then + printf -- '-- Sourcing zshrc environment loader ... (found at "%s")\n' "${HOME}/.zshrc" + source "${HOME}/.zshrc" &> /dev/null +else + printf -- '-- Skipping zshrc environment loader ... (found it has already been loaded)\n' +fi + +CALL_EXEC="${1}"; shift + +printf -- '-- Invoking passed command and arguments ... (calling "%s")\n' ""${CALL_EXEC}" "${@}"" +printf -- '!! Pausing for 10 seconds. Cancel using CNTL-C [00' + +SLEEP_TICK=40 +SLEEP_SECS=0 + +for i in $(seq 1 ${SLEEP_TICK}); do + if [[ $((i % 4)) == 0 ]]; then + ((SLEEP_SECS++)) + printf '%02d' "${SLEEP_SECS}" + else + printf '.' + fi + + sleep 0.25 +done + +printf ']\n' + +sleep 1 && clear + +"${CALL_EXEC}" "${@}" + diff --git a/bin-available/colors.bash b/bin-available/colors.bash new file mode 100755 index 0000000..6660f76 --- /dev/null +++ b/bin-available/colors.bash @@ -0,0 +1,80 @@ +ui_reset='\033[21m\033[22m\033[24m\033[25m\033[27m\033[28m\033[0m' + +ui_powerline_char_n=(pointingarrow arrowleft arrowright arrowrightdown arrowdown plusminus branch refersto ok fail lightnight cog heart star saxophone thumbsup) +ui_powerline_char_i=0 +ui_powerline_pointingarrow='\u27a1' +ui_powerline_arrowleft='\ue0b2' +ui_powerline_arrowright='\ue0b0' +ui_powerline_arrowrightdown='\u2198' +ui_powerline_arrowdown='\u2b07' +ui_powerline_plusminus='\ue00b1' +ui_powerline_branch='\ue0a0' +ui_powerline_refersto='\u27a6' +ui_powerline_ok='\u2714' +ui_powerline_fail='\u2718' +ui_powerline_lightning='\u26a1' +ui_powerline_cog='\u2699' +ui_powerline_heart='\u2764' +ui_powerline_star='\u2b50' +ui_powerline_saxophone='\u1f3b7' +ui_powerline_thumbsup='\u1f44d' + +ui_color_name_n=(default black red green yellow blue magenta cyan lightgray darkgray lightred lightgreen lightyellow lightblue lightmagenta lightcyan white) +ui_color_name_i=0 +ui_color_black='\033[0;30m' +ui_color_red='\033[0;31m' +ui_color_green='\033[0;32m' +ui_color_yellow='\033[0;33m' +ui_color_blue='\033[0;34m' +ui_color_magenta='\033[0;35m' +ui_color_cyan='\033[0;36m' +ui_color_lightgray='\033[0;37m' +ui_color_darkgray='\033[0;90m' +ui_color_lightred='\033[0;91m' +ui_color_lightgreen='\033[0;92m' +ui_color_lightyellow='\033[0;93m' +ui_color_lightblue='\033[0;94m' +ui_color_lightmagenta='\033[0;95m' +ui_color_lightcyan='\033[0;96m' +ui_color_white='\033[0;97m' + +ui_color_bold='\033[1m' +ui_color_dim='\033[2m' +ui_color_underline='\033[4m' +ui_color_blink='\033[5m' +ui_color_invert='\033[7m' +ui_color_invisible='\033[8m' + +for i in 1 2 3 4 5 6 7 8 20 18 17; do + printf '[%d] ' "${i}" +done +printf '\n' + +for f in "${ui_powerline_pointingarrow}" "${ui_powerline_arrowleft}" "${ui_powerline_arrowright}" "${ui_powerline_arrowrightdown}" "${ui_powerline_arrowdown}" "${ui_powerline_plusminus}" "${ui_powerline_branch}" "${ui_powerline_refersto}" "${ui_powerline_ok}" "${ui_powerline_fail}" "${ui_powerline_lightning}" "${ui_powerline_cog}" "${ui_powerline_heart}" "${ui_powerline_star}" "${ui_powerline_saxophone}" "${ui_powerline_thumbsup}"; do + + echo -en "$( + printf 'FONT-CHAR[%s]' "${ui_powerline_char_n[${ui_powerline_char_i}]}" + )" + + for c in "${ui_reset}" "${ui_color_black}" "${ui_color_red}" "${ui_color_green}" "${ui_color_yellow}" "${ui_color_blue}" "${ui_color_magenta}" "${ui_color_cyan}" "${ui_color_lightgray}" "${ui_color_darkgray}" "${ui_color_lightred}" "${ui_color_lightgreen}" "${ui_color_lightyellow}" "${ui_color_lightblue}" "${ui_color_lightmagenta}" "${ui_color_lightcyan}" "${ui_color_white}"; do + + echo -en "$( + printf '\n %12s => "%s"' "${ui_color_name_n[${ui_color_name_i}]}" "${c}${f}${ui_reset}" + )" + + + ui_color_name_i=$((${ui_color_name_i} + 1)) + if [[ ${ui_color_name_i} -gt $((${#ui_color_name_n[@]} - 1)) ]]; then + ui_color_name_i=0 + fi + + done + + printf '\n' + + ui_powerline_char_i=$((${ui_powerline_char_i} + 1)) + if [[ ${ui_powerline_char_i} -gt ${#ui_powerline_char_n[@]} ]]; then + ui_powerline_char_i=0 + fi + +done diff --git a/bin-available/composer-download-global.bash b/bin-available/composer-download-global.bash new file mode 100755 index 0000000..e7983be --- /dev/null +++ b/bin-available/composer-download-global.bash @@ -0,0 +1,117 @@ +#!/bin/bash + +set -e + +readonly SELF_FILE_PATH="$(readlink -m ${BASH_SOURCE[0]})" +readonly SELF_BASE_NAME="$(basename "${SELF_FILE_PATH}" .bash)" +readonly SELF_WORK_PATH="/tmp/${SELF_BASE_NAME}-${RANDOM}" +readonly COMP_INST_LINK="https://getcomposer.org/installer" +readonly COMP_INST_FILE="composer-installer.php" +readonly COMP_INST_ALGO="sha384" +readonly COMP_INST_HASH="48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5" +readonly COMP_INST_SUMS="$(tr '[:lower:]' '[:upper:]' <<< "${COMP_INST_ALGO}")SUMS" + +function format_text { + local format="${1}" + local argums=("${@:2}") + + printf -- '%s (%.06f) -- %s' \ + "${SELF_BASE_NAME}" \ + "$(date +%s.%N)" \ + "$(printf -- "${format}" "${argums[@]}")" +} + +function format_line { + format_text "${@}" + printf '\n' +} + +function action_definition { + format_text "${1} ... " "${@:2}" +} + +function action_def { + action_definition "${@}" +} + +function action_resolution { + local status="${1:-0}" + local format="${2:-}" + local argums=("${@:3}") + +# printf '\nSTATUS[%d]\nFORMAT[%s]\n' "${status}" "${format}" +# printf 'ARGUMS[%s]\n' "${argums[@]}" + + if [[ ${status} -ne ${expect} ]]; then + printf '[FAIL]' + + if [[ -n ${format} ]]; then + printf -- ' (%s)' \ + "$(printf -- "${format}" "${argums[@]}")" + fi + + printf '\n' + exit ${status} + fi + + printf '[DONE]\n' +} + +function action_res { + action_resolution "${@}" +} + +format_text 'Calling custom output function: "%s"' 'format_text' +format_line 'SAME LINE AS FIRST' + +format_line 'FOO[%s] BAR[%s] BAZ[%s]' ${RANDOM} ${RANDOM} ${RANDOM} + +action_definition 'Begin "%s" action and determine result afterwards' "foobar-${RANDOM}" +action_resolution 0 'could not determine "%s" or "%s" for "%s"' 'foo' 'bar' "${RANDOM}" +action_definition 'Begin "%s" action and determine result afterwards' "foobar-${RANDOM}" +action_resolution 1 'could not determine "%s" or "%s" for "%s"' 'foo' 'bar' "${RANDOM}" +action_definition 'Begin "%s" action and determine result afterwards' "foobar-${RANDOM}" +action_resolution 255 'could not determine "%s" or "%s" for "%d"' 'foo' 'bar' "${RANDOM}" +action_def 'Begin "%s" action and determine result afterwards' "foobar-${RANDOM}" +action_res 0 'could not determine "%s" or "%s" for "%s"' 'foo' 'bar' "${RANDOM}" +action_def 'Begin "%s" action and determine result afterwards' "foobar-${RANDOM}" +action_res 1 'could not determine "%s" or "%s" for "%s"' 'foo' 'bar' "${RANDOM}" +action_def 'Begin "%s" action and determine result afterwards' "foobar-${RANDOM}" +action_res 255 'could not determine "%s" or "%s" for "%s"' 'foo' 'bar' "${RANDOM}" +write_line 'Replacements with spaces: "%s", "%d", and "%s"' 'foo bar baz' 192883 'a b c d e f g' +action_def 'Begin "%s" action using replacements with spaces "%s" and "%s"' 'foo bar baz' 'a b c d e f g' +action_res 0 'explanation using replacements with spaces: "%s" or "bar"' 'foo bar baz' 'a b c d e f g' +action_def 'Begin "%s" action using replacements with spaces "%s" and "%s"' 'foo bar baz' 'a b c d e f g' +action_res 255 'explanation using replacements with spaces: "%s" or "bar"' 'foo bar baz' 'a b c d e f g' +action_definition 'Begin "%s" action using replacements with spaces "%s" and "%s"' 'foo bar baz' 'a b c d e f g' +action_resolution 0 'explanation using replacements with spaces: "%s" or "bar"' 'foo bar baz' 'a b c d e f g' +action_definition 'Begin "%s" action using replacements with spaces "%s" and "%s"' 'foo bar baz' 'a b c d e f g' +action_resolution 255 'explanation using replacements with spaces: "%s" or "bar"' 'foo bar baz' 'a b c d e f g' +exit + + +if [[ -d ${SELF_WORK_PATH} ]]; then + format_line 'Removing temporary work directory: "%s" (from prior run)\n' "${SELF_WORK_PATH}" + rm -vdr "${SELF_WORK_PATH}" +fi + +printf 'Creating temporary work directory: "%s"\n' "${SELF_WORK_PATH}" +mkdir -p "${SELF_WORK_PATH}" + +printf 'Entering temporary work directory: "%s"\n' "${SELF_WORK_PATH}" +cd "${SELF_WORK_PATH}" + +printf 'Fetching composer installer script: "%s"\n' "${COMP_INST_LINK}" +curl -so "${COMP_INST_FILE}" "${COMP_INST_LINK}" + +printf 'Creating composer installer hash integrety definition file: "%s"\n' "${}" + +printf 'Checking composer installer script matches expected file hash: "%s"\n' "${COMP_INST_HASH}" +sha384sum -c installer.sha384 --status; echo $?; "48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5 installer.php" + +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" +php composer-setup.php +php -r "unlink('composer-setup.php');" +chmod u+x composer.phar +sudo mv composer.phar /usr/local/bin/composer diff --git a/bin-available/bash.bash b/bin-available/ip-public-enp7s0.bash old mode 100644 new mode 100755 similarity index 62% rename from bin-available/bash.bash rename to bin-available/ip-public-enp7s0.bash index 9603dc5..7b8a661 --- a/bin-available/bash.bash +++ b/bin-available/ip-public-enp7s0.bash @@ -9,7 +9,4 @@ ## file that was distributed with this source code. ## -printf 'B0:"%s"\n' "${BASH_SOURCE[0]}" -printf 'B1:"%s"\n' "${BASH_SOURCE[1]}" -printf 'B2:"%s"\n' "${BASH_SOURCE[2]}" -printf 'B3:"%s"\n' "${BASH_SOURCE[3]}" +bash $(dirname "$(readlink -m "${0}")")/ip-info.bash -i=enp7s0 -m -q -r | tr -d '\n' diff --git a/bin-available/ip-public-tun0.bash b/bin-available/ip-public-tun0.bash index 03b514e..5afa3e1 100755 --- a/bin-available/ip-public-tun0.bash +++ b/bin-available/ip-public-tun0.bash @@ -9,5 +9,5 @@ ## file that was distributed with this source code. ## -bash $(dirname "$(readlink -m "${0}")")/ip-info.bash -i=tun0 -r | tr -d '\n' +bash $(dirname "$(readlink -m "${0}")")/ip-info.bash -i=tun0 -m -q -r | tr -d '\n' diff --git a/bin-available/magnet-queue.bash b/bin-available/magnet-queue.bash index 2637f38..17e2664 100755 --- a/bin-available/magnet-queue.bash +++ b/bin-available/magnet-queue.bash @@ -1,55 +1,12 @@ -#!/bin/bash +#!/usr/bin/env bash -function get_output_root() -{ - local config_path="${HOME}/.torrent-magnets-path" +readonly MAGNET_QUEUE_SCR_REL_PATH="${BASH_SOURCE[0]}" +readonly MAGNET_QUEUE_SCR_ABS_PATH="$( + printf "r='${MAGNET_QUEUE_SCR_REL_PATH}'; printf '%%s' \"\${r:A}\"" | zsh +)" +readonly MAGNET_QUEUE_SCR_DIR_PATH="$(dirname "${MAGNET_QUEUE_SCR_ABS_PATH}")" - if [[ -f "${config_path}" ]]; then - cat "${HOME}/.torrent-magnets-path" 2> /dev/null - else - printf './' - fi -} +printf 'MAGNET_QUEUE_SCR_REL_PATH[%s]\n' "${MAGNET_QUEUE_SCR_REL_PATH}" +printf 'MAGNET_QUEUE_SCR_ABS_PATH[%s]\n' "${MAGNET_QUEUE_SCR_ABS_PATH}" +printf 'MAGNET_QUEUE_SCR_DIR_PATH[%s]\n' "${MAGNET_QUEUE_SCR_DIR_PATH}" -function out_error() { - local message="${1}" - shift - - printf 'ERROR: %s\n' "$(printf "${message}" $@)" -} - -function out_usage() { - printf 'Usage: ./%s <magnet-link> [<output_root>]\n' "$(basename ${BASH_SOURCE})" -} - -function main() { - local magnet_link="${1:-x}" - local output_root="$(get_output_root)" - - if [[ ! -w "${output_root}" ]]; then - out_error 'Output path "%s" is not writable!' "${output_root}" - out_usage - exit 255 - fi - - if [[ "${magnet_link}" == "x" ]]; then - out_error 'You must specify a magnet link as the first argument!' - out_usage - exit 255 - fi - - local magnet_file="$(echo ${magnet_link} | grep -oE '=([^=&]+)' | head -n2 | tail -n 1 | grep -oE '[A-Za-z].+$').magnet" - local magnet_path="${output_root}/${magnet_file}" - - echo "${magnet_link}" > "${magnet_path}" - - if [[ $? -eq 0 ]]; then - printf 'Writing magnet: %s\n' "${magnet_path}" - else - printf 'Error writing magnet: %s\n' "${magnet_path}" - fi -} - -for magnet_link in "$@"; do - main "${magnet_link}" -done diff --git a/bin-available/magnet-queue.bash.bk b/bin-available/magnet-queue.bash.bk new file mode 100755 index 0000000..8afe6b2 --- /dev/null +++ b/bin-available/magnet-queue.bash.bk @@ -0,0 +1,173 @@ +#!/bin/bash + +# +# defile the file where a torrent magnets output path is defined inside +# +TORRENT_MAGNETS_CAT_PATH="${HOME}/.torrent-magnets-path" + +# +# define the default torrent magnets output path +# +TORRENT_MAGNETS_DEF_PATH="/tmp/torrent-magnets/" + +# +# get the name of this script +# +function get_self_name() { + printf '%s' "$(basename "${BASH_SOURCE[0]}" ".bash")" +} + +# +# output line prefix info +# +function out_pref() { + local type="${1:-info}" + + printf '(%s:%f.04) [%s]' "$(get_self_name)" "$(date +%s.%N)" "${type^^}" +} + +# +# output info message +# +function out_info() { + local message="${1}" + local replace=("${@:2}") + + + printf "%s ${message}\n" "$(out_pref 'info')" "${replace[@]}" +} + +# +# output critical message +# +function out_crit() { + local message="${1}" + local replace=("${@:2}") + + printf "%s ${message}\n" "$(out_pref 'crit')" "${replace[@]}" 1>&2 +} + +# +# output help/usage message +# +function out_help() { + printf 'Usage: ./%s MAGNET_LINK_1 [... MAGNET_LINK_N]\n' "$(get_self_name)" 1>&2 +} + +# +# get the torrent file output root directory +# +function get_torrent_magnets_path() { + cat "${TORRENT_MAGNETS_CAT_PATH}" 2> /dev/null \ + || (\ + printf '%s' "${TORRENT_MAGNETS_DEF_PATH}" \ + && out_crit \ + 'Failed to read output path config path from file "%s" (falling back to "%s" as output path)...' \ + "${TORRENT_MAGNETS_CAT_PATH}" \ + "${TORRENT_MAGNETS_DEF_PATH}" \ + ) +} + +# +# resolve the latest python binary path +# +function get_python_bin() { + local bin_path + + if ! bin_path="$(which python3)"; then + if ! bin_path="$(which python)"; then + if ! bin_path="$(which python2)"; then + return 1 + fi + fi + fi + + printf '%s' "${bin_path}" +} + +# +# decode special url characters +# +function url_decode() { + local input_link="${1}" + local clean_link + local python_bin="$(get_python_bin)" + + if -x "${python_bin}"; then + clean_link="$( + python \ + -c "import sys, urllib as ul; print ul.unquote_plus(sys.argv[1])" \ + "${url_raw}" + )" + fi + + printf '%s' "${clean_link:-${input_link}}" +} + +# +# check runtime output root var +# +function check_output() { + local output_root="${1}" + + if [[ -z "${output_root}"; then + out_error 'No output root configured for environment in ' + fi + + if [[ ! -d "${output_root}"; then + + fi + + if [[ ! -w "${output_root}" ]]; then + out_crit 'Output path "%s" is not writable!' "${output_root}" + out_help + exit 255 + fi +} + + +function main() { + local output_root="$(get_torrent_magnets_path)" + local magnet_link="${1:-x}" + local magnet_file + local magnet_path + local raw_in_file + + if [[ ! -w "${output_root}" ]]; then + out_crit 'Output path "%s" is not writable!' "${output_root}" + out_help + exit 255 + fi + + if [[ "${magnet_link}" == "x" ]]; then + out_crit 'You must specify a magnet link as the first argument!' + out_help + exit 255 + fi + + raw_in_file="$(grep -oE '=([^=&]+)' <<< "${magnet_link}" | head -n2 | tail -n1 | grep -oE '[A-Za-z].+$')" + magnet_file="$(sed -E 's/ /_/g' <<< "$(url_decode "${raw_in_file}")")" + + if ! magnet_file="$(url_decode "${raw_in_file}")"; then + out_crit '' + +sed -E 's/ /_/g' + magnet_link + magnet_link="${magnet_link// /_}" + printf 'Cleaned magnet file characters: "%s" (from "%s")' + + magnet_file="$(echo ${magnet_link} | grep -oE '=([^=&]+)' | head -n2 | tail -n 1 | grep -oE '[A-Za-z].+$').magnet" + magnet_path="${output_root}/${magnet_file}" + + echo "${magnet_link}" > "${magnet_path}" + + if [[ $? -eq 0 ]]; then + out_info 'Writing magnet: %s' "${magnet_path}" + else + out_crit 'Error writing magnet: %s' "${magnet_path}" + fi +} + +for magnet_link in "$@"; do + main "${magnet_link}" +done diff --git a/bin-available/magnet-to-torrent-watcher.bash b/bin-available/magnet-to-torrent-watcher.bash index 9864dda..f21d126 100755 --- a/bin-available/magnet-to-torrent-watcher.bash +++ b/bin-available/magnet-to-torrent-watcher.bash @@ -1,11 +1,20 @@ #!/bin/bash +## +## This file is part of the `robfrawley/twoface-scripts` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + # # configuration variables # WATCH_TICK=1 WATCH_ECHO_TICK=20 -MAGNET_BIN="$(which magnet-to-torrent-writer)" +MAGNET_BIN="/home/rto/scripts/bin-enabled/magnet-to-torrent-writer" MAGNET_LOG="/tmp/magnet-to-torrent-watcher_${RANDOM}.log" # @@ -79,7 +88,7 @@ function run_resolve_file() { local magnet_link="${1}" local torrent_out="${2}" - ${MAGNET_BIN} -m "${magnet_link}" -o "${torrent_out}" &> ${MAGNET_LOG} & + ${MAGNET_BIN} -m "${magnet_link}" -o "${torrent_out}" &> "${MAGNET_LOG}" & echo "$!" } @@ -96,6 +105,7 @@ function run_resolve() { cd "$(get_output_root)" out_resolve_info "${magnet_link}" "${torrent_out}" "${magnet_file}" + echo -e "\n[EXEC] ${MAGNET_BIN} -m '${magnet_link}' -o '${torrent_out}' &> '${MAGNET_LOG}' &\n" &> "${MAGNET_LOG}" & local pid=$(run_resolve_file "${magnet_link}" "${torrent_out}") out_resolve_done ${pid} "${magnet_file}" } @@ -150,10 +160,33 @@ function do_pause_state() { printf 'waking (found %d new magnet links)...\n' $(get_magnet_count) } +# +# output runtime configuration +# +function out_configuration() +{ + printf '##\n' + printf '## CONFIGURATIOM\n' + printf '##\n\n' + printf 'WATCH_LOOP_TICK => "%d"\n' "${WATCH_TICK}" + printf 'WATCH_ECHO_TICK => "%d"\n' "${WATCH_ECHO_TICK}" + printf 'MAGNET_BIN_PATH => "%s"\n' "${MAGNET_BIN}" + printf 'MAGNET_LOG_FILE => "%s"\n' "${MAGNET_LOG}" + printf 'MAGNET_GET_PATH => "%s"\n' "$(get_magnet_root)" + printf 'OUTPUT_SET_PATH => "%s"\n\n' "$(get_output_root)" +} + # # the main function # function main() { + out_configuration + + printf '##\n' + printf '## MAGNET WATCHER\n' + printf '##\n\n' + + while true; do if [[ $(get_magnet_count) -gt 0 ]]; then do_magnet_loop diff --git a/bin-available/mague-args.bash b/bin-available/mague-args.bash new file mode 100755 index 0000000..5afe4ed --- /dev/null +++ b/bin-available/mague-args.bash @@ -0,0 +1,292 @@ +#!/usr/bin/env bash + +## +## This file is part of the `src-run/bash-server-scripts` project. +## +## (c) https://github.com/src-run/bash-server-scripts/graphs/contributors +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +#=region-init:import + +# import core modules + +# source default module loader +source "$( + dirname "$( + readlink -m "${BASH_SOURCE[0]}" + )" +)/../lib/resrc/setup.bash" + +#=region-ends:modules +#=region-init:docs + +mague__doc__=' + Pass any number of magnet links to this command as command line arguments. +' + +#=region-ends:docs +#=region-init:variables + +# resolve the real command file path +readonly mague_cmd_self="$( + printf 'r="'"${BASH_SOURCE[0]}"'"; printf '%s' "${r:A}"' | /usr/bin/env zsh 2> /dev/null +)" + +# resolve the real command directory path +readonly mague_cmd_path="$( + dirname "${mague_cmd_self}" 2> /dev/null +)" + +# resolve the real command file name +readonly mague_cmd_file="$( + basename "${mague_cmd_self}" 2> /dev/null +)" + +# resolve the real command name (file basename) +readonly mague_cmd_name="$( + basename "${mague_cmd_self}" "$( + grep -oE '\.[a-z0-9]+$' <<< "${mague_cmd_file}" 2> /dev/null + )" 2> /dev/null +)" + +# define the write path config file location +mague_write_path_cfg_loc="${mague_write_path_cfg_loc:-${HOME}/.mague-write-path.conf}" + +# define the write path config default value +mague_write_path_cfg_def="${mague_write_path_cfg_def:-$(pwd)/${mague_cmd_name}/}" + +# define the write path config runtime value +mague_write_path_cfg_val='' + +#=region-ends:variables +#=region-init:functions + +# write to stdout with printf-style replacements +mague_write_stdout() { + printf -- "${@}" +} + +# write to stderr with printf-style replacements +mague_write_stderr() { + 1>&2 printf -- "${@}" +} + +# +# output help/usage message +# +mague_write_usage() { + mague_write_stderr 'USAGE\n' + mague_write_stderr ' ./%s mag_link_1 [mag_link_2] [...] [mag_link_n]\n\n' "${mague_cmd_file}" + mague_write_stderr 'ARGUMENTS\n' + mague_write_stderr ' -%s|--%-8s %s\n' o root 'Ignore globally configured path and output magnet files to this location instead.' + mague_write_stderr ' -%s|--%-8s %s\n' v verbose 'Enable verbose logging of actions performed by this command.' + mague_write_stderr ' -%s|--%-8s %s\n' d debug 'Enable debug-level logging of actions performed by this command.' + mague_write_stderr ' -%s|--%-8s %s\n' u usage 'Output usage information for this command.' +} + +# sets logger verbosity level +mague_set_verbosity() { + local lev="${1:-info}" + + logging.set_level "${lev}" + logging.set_commands_level "${lev}" + logger.debg 'Setting runtime log level: "%s"...' "${lev}" +} + +# create the magnet link output path config +function mague_cfg_write_path_make() { + local write_path="${1}" + + if mkdir -p "${write_path}" 2> /dev/null; then + logger.verb 'Creating magnet link output path: "%s"...' "${write_path}" + return + fi + + return 1 +} + +# check the magnet link output path config +function mague_cfg_write_path_check() { + local write_path="${1}" + + if ([[ -d ${write_path} ]] && [[ -r ${write_path} ]]) || mague_cfg_write_path_make "${write_path}"; then + logger.verb 'Resolved magnet link output path: "%s"...' "${write_path}" + return + fi + + return 1 +} + +# gets the magnet link output path config +function mague_cfg_write_path_set() { + if [[ -f ${mague_write_path_cfg_loc} ]] && [[ -r ${mague_write_path_cfg_loc} ]]; then + mague_write_path_cfg_val="$( + cat "${mague_write_path_cfg_loc}" + )" + else + mague_write_path_cfg_val="${mague_write_path_cfg_def}" + fi + + if ! mague_cfg_write_path_check "${mague_write_path_cfg_val}"; then + logger.exit 'Failure encountered while resolving magnet link output path...' + fi +} + +# resolve the latest php executable path +function mague_get_php_bin() { + local bin_path + local possible=(php7.4 php7.3 php7.2 php7.1 php7.0 php7 php) + + for p in "${possible[@]}"; do + if bin_path="$(command -v "${p}")"; then + printf '%s' "${bin_path}" && return + fi + done + + return 1 +} + +# decode special url characters +function mague_link_decode() { + local mag_link="${1}" + local dec_link + local php_path + +#sed -E 's/\$/-/g' <<< '!@#$%^&*()$$$' +#php7.3 -r 'echo(trim(preg_replace("{[_]+}", "_", preg_replace("{[^a-z0-9_-]+}i", "_", "!@#$%^&*()_+-=1234567890[]\{}|;:\",./<>?q!w@e#rt%y^u&i*o(pasdfghjklzxcvbnm")), "-_\t\n\r\0\x0B"));' + + if php_path="$(mague_get_php_bin)"; then + dec_link="$( + ${php_path} -r 'echo(trim(preg_replace("{[_]+}", "_", preg_replace("{[^a-z0-9?&[\\\._-]+}i", "_", str_replace([" ", "\t", "\r", "\n"], "_", urldecode($argv[1])))), "-_\t\n\r\0\x0B"));' "$(sed -E 's/\$/-/g' <<< "${mag_link}")" +#'echo(trim(preg_replace("{[_]+}", "_", preg_replace("{[^a-z0-9_-]+}i", "_", str_replace([" ", "\t", "\r", "\n"], "_", urldecode($argv[1])))), , "-_\t\n\r\0\x0B"));' "$(sed -E 's/\$/-/g' <<< "${mag_link}")" +#2> /dev/null \ +# || printf '%s' "${mag_link}-decode-failed" + )" + fi + + #if php_path="$(mague_get_php_bin)"; then + # dec_link="$( + # ${php_path} -r 'echo(str_replace([" ", "\t", "\r", "\n"], "_", urldecode($argv[1])));' "${mag_link}" 2> /dev/null \ + # || printf '%s' "${mag_link}" + # )" + #fi + + printf '%s' "${dec_link:-${mag_link}}" +} + +# encode special url characters +function mague_link_encode() { + local mag_link="${1}" + local dec_link + local php_path + + if php_path="$(mague_get_php_bin)"; then + dec_link="$( + ${php_path} -r 'echo(rawurlencode($argv[1]));' "${mag_link}" 2> /dev/null + )" + fi + + printf '%s' "${dec_link:-${mag_link}}" +} + +# handle the passed magnet link +mague_handle_link() { + local out_path="${1}" + local mag_link="${2}" + local mag_file + local mag_path + + if [[ -z "${mag_link}" ]]; then + logger.warn 'An empty magnet link was provided. Skipping entry...' + return + fi + + logger.debg 'Parsing magnet of link: "%s"...' "$(mague_link_encode "${mag_link}")" + + mag_file="$( + sed -E 's/ /_/g' <<< "$( + mague_link_decode "$( + grep -oE '=([^=&]+)' <<< "${mag_link}" 2> /dev/null | \ + head -n2 2> /dev/null | \ + tail -n1 2> /dev/null + )" + )" 2> /dev/null + )" + mag_file="$( + grep -oE '[A-Za-z].+\.[A-Za-z0-9]{1,4}' 2> /dev/null <<< "${mag_file}" \ + || grep -oE '[A-Za-z].+$' 2> /dev/null <<< "${mag_file}" + ).magnet" + + mag_path="${out_path}/${mag_file}" + + logger.debg 'Decoded magnet link path: "%s"...' "${mag_path}" + logger.info 'Writing magnet link file: "%s"...' "${mag_file}" + + if echo "${mag_link}" > "${mag_path}" 2> /dev/null; then + logger.debg 'Success writing magnet link file: "%s"...' "${mag_file}" + else + logger.debg 'Failure writing magnet link file: "%s"...' "${mag_file}" + fi +} + +# main command logic loop +mague_main() { + local out_help=false + local log_debg=false + local log_verb=false + local mag_urls=() + local out_path + + arguments.set "${@}" + mag_urls=($(arguments.get_parameters_not_named --debug -d --verbose -v --root -r)) + + arguments.get_flag --usage -u --help -h out_help + if "${out_help}"; then + mague_write_usage + exit 0 + fi + + arguments.get_flag --debug -d log_debg + if "${log_debg}"; then + mague_set_verbosity debug + fi + + arguments.get_flag --verbose -v log_verb + if "${log_verb}"; then + mague_set_verbosity verbose + fi + + arguments.get_parameter --root -r out_path + arguments.get_keyword --root -r out_path + + if ! mague_cfg_write_path_check "${out_path}"; then + mague_cfg_write_path_set + out_path="${mague_write_path_cfg_val}" + fi + + if [[ ${#mag_urls[@]} -eq 0 ]]; then + logger.warn 'No magnet links were passed as arguments. Nothing to do...' + exit 0 + fi + + for l in "${mag_urls[@]}"; do + mague_handle_link "${out_path}" "${l}" + done +} + +#=region-ends:functions +#=region-init:interfaces + +#=region-ends:interfaces +#=region-init:main-sub + +if core.is_main; then + mague_main "${@}" + exit $? +fi + +#=region-ends:main-sub + diff --git a/bin-available/mague-file.bash b/bin-available/mague-file.bash new file mode 100755 index 0000000..940d232 --- /dev/null +++ b/bin-available/mague-file.bash @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +## +## This file is part of the `src-run/bash-server-scripts` project. +## +## (c) https://github.com/src-run/bash-server-scripts/graphs/contributors +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +function process_file() +{ + local -r file_path="${1}" + local -r exec_path="${2}" + + if [[ ! -e "${file_path}" ]] || [[ ! -r "${file_path}" ]]; then + printf -- '[ERROR] File "%s" does not exist or is not readable!\n' "${file_path}" + return 1 + fi + + mapfile -t < "${file_path}" + + for l in "${MAPFILE[@]}"; do + if [[ "${l:0:7}" == 'magnet:' ]]; then + "${exec_path}" "${l}" + fi + done +} + +function main() { + local -a file_list=("${@}") + local -r exec_name='mague-args' + local -r exec_path="$( + command -v "${exec_name}" \ + || printf -- '%s/%s.bash' "$(dirname "$(readlink -m "${0}")")" "${exec_name}" + )" + + if [[ ! -e "${exec_path}" ]] || [[ ! -x "${exec_path}" ]]; then + printf -- '[ERROR] Sub-command executable "%s" does not exist or is not executable!\n' "${exec_path:-${exec_name}}" + return 1 + fi + + for f in "${file_list[@]}"; do + process_file "${f}" "${exec_path}" + done +} + +main "${@}" diff --git a/bin-available/monitor-torrent-watcher.bash b/bin-available/monitor-torrent-watcher.bash new file mode 100755 index 0000000..776ddc9 --- /dev/null +++ b/bin-available/monitor-torrent-watcher.bash @@ -0,0 +1,23 @@ +#!/bin/bash + +## +## This file is part of the `robfrawley/twoface-scripts` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +while true; do + while [[ $(ps aux | grep magnet | grep -oE 'magnet:\?.+ -'| wc -l) -gt 0 ]]; do + clear + printf "Found %d magnet conversion process identifiers ... (%s)\n" "$(ps aux | grep magnet | grep -oE 'magnet:\?.+ -'| wc -l)" "$(date)" + ps aux | grep magnet | grep -oE 'magnet:\?.+ -' | awk '{ printf "- %s\n", $1 }' + sleep 2 + done + + clear + echo "Found 0 magnet conversion process identifiers ... (sleeping)" + sleep 2 +done diff --git a/bin-available/start-glances.bash b/bin-available/start-glances.bash index c937ebf..5545e7e 100755 --- a/bin-available/start-glances.bash +++ b/bin-available/start-glances.bash @@ -1,3 +1,3 @@ #!/bin/bash -sudo glances 2> /dev/null +/pool/scripts/bin-enabled/glances -D diff --git a/bin-available/start-openvpn.bash b/bin-available/start-openvpn.bash new file mode 100755 index 0000000..86d5da6 --- /dev/null +++ b/bin-available/start-openvpn.bash @@ -0,0 +1,96 @@ +#!/bin/bash + +## +## This file is part of the `robfrawley/twoface-scripts` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +OPENVPN_SCR_NAME="$(basename "${BASH_SOURCE[0]}")" + +OPENVPN_BIN_FILE="$(which openvpn)" +OPENVPN_VER_OVPN="$("${OPENVPN_BIN_FILE}" --version 2> /dev/null | grep -oE '(OpenVPN) [0-9\.]+' | sed -E 's/([a-zA-Z]+) ([0-9\.]+)/\1 v\2/g')" +OPENVPN_VER_OSSL="$("${OPENVPN_BIN_FILE}" --version 2> /dev/null | grep -oE '(OpenSSL) [0-9\.]+' | sed -E 's/([a-zA-Z]+) ([0-9\.]+)/\1 v\2/g')" +OPENVPN_VER_CLZO="$("${OPENVPN_BIN_FILE}" --version 2> /dev/null | grep -oE '(LZO) [0-9\.]+' | sed -E 's/([a-zA-Z]+) ([0-9\.]+)/\1 v\2/g')" + +OPENVPN_DIR_PATH="${HOME}/ovpn" +OPENVPN_RUN_FILE="${OPENVPN_DIR_PATH}/openvpn.status" +OPENVPN_PID_FILE="${OPENVPN_DIR_PATH}/openvpn.pid" +OPENVPN_LOG_FILE="${OPENVPN_DIR_PATH}/openvpn.log" +OPENVPN_LOG_LEVL=3 +OPENVPN_DEV_NAME='tun0' +OPENVPN_CFG_FILE="${OPENVPN_DIR_PATH}/pia-vpn-usa.ovpm" +OPENVPN_BIN_OPTS="--cd ${OPENVPN_DIR_PATH} --status ${OPENVPN_RUN_FILE} 10 --config ${OPENVPN_CFG_FILE} --mute-replay-warnings --dev ${OPENVPN_DEV_NAME} --verb ${OPENVPN_LOG_LEVL}" + +OPENVPN_PID_INTS="$(pidof ${OPENVPN_BIN_FILE})" +OPENVPN_RUN_OKAY=1 +OPENVPN_RUN_WAIT=5 + +OPENVPN_VAR_PRFX='OPENVPN' +OPENVPN_VAR_KEYS=('BIN_FILE' 'VER_OVPN' 'VER_OSSL' 'VER_CLZO' 'DIR_PATH' 'RUN_FILE' 'PID_FILE' 'LOG_FILE' 'LOG_LEVL' 'DEV_NAME' 'CFG_FILE' 'BIN_OPTS' 'BIN_INTS' 'RUN_OKAY' 'RUN_WAIT') + +function o_text { + printf -- "${@}" +} + +while true; do + OPENVPN_RUN_OKAY=1 + OPENVPN_PID_INTS="$(pidof ${OPENVPN_BIN_FILE})" + OPENVPN_RUN_WAIT="${OPENVPN_RUN_WAIT:-5}" + + clear + + o_text '\n##\n## DATE => "%s"\n## NAME => "%s"\n##\n' "$(date)" "${OPENVPN_SCR_NAME}" + o_text '\n--\n-- RESOLVED RUNTIME CONFIGURATION\n--\n' + + for n in "${OPENVPN_VAR_KEYS[@]}"; do + v="$(printf '%s_%s' "${OPENVPN_VAR_PRFX}" "${n}")" + c="${!v}" + + o_text '-- • %s => "%s"' "${v}" "${c}" + + if [[ ${n} =~ PATH$ ]] && [[ ! -d ${!v} ]]; then + o_text ' (Error: The configured path does not exist!)' + OPENVPN_RUN_OKAY=0 + sleep 1 + fi + + if [[ ${n} =~ FILE$ ]] && [[ ! ${n} =~ (PID|LOG|RUN) ]] && [[ ! -f ${!v} ]]; then + o_text ' (Error: The configured file does not exist!)' + OPENVPN_RUN_OKAY=0 + sleep 1 + fi + + o_text '\n' + done + + o_text '--\n' + + if [[ ${OPENVPN_PID_INTS} != "" ]]; then + o_text '\n!!\n!! Unable to start openvpn as it is already running as "%s" ...\n!!\n' "${OPENVPN_PID}" + OPENVPN_RUN_OKAY=0 + fi + + if [[ ${OPENVPN_RUN_OKAY} -eq 0 ]]; then + o_text '\n!!\n!! Sleeping for %d seconds before restarts openvpn script due to failures detailed aboves ...\n!!\n' "${OPENVPN_RUN_WAIT}" + sleep ${OPENVPN_RUN_WAIT} + continue + else + o_text '\n!!\n!! Sleeping for %d seconds before invoking openvpn using the above configs ...\n!!\n' "${OPENVPN_RUN_WAIT}" + sleep ${OPENVPN_RUN_WAIT} + fi + + cd "${OPENVPN_DIR_PATH}" + + o_text '\n' + + sudo "${OPENVPN_BIN_FILE}" ${OPENVPN_BIN_OPTS} + + o_text '\n!!\n!! Caught exited openvpn process ... attempting to restart after waiting for %d seconds ...\n!!\n' "${OPENVPN_RUN_WAIT}" + + sleep ${OPENVPN_RUN_WAIT} +done + diff --git a/bin-available/start-rtorrent.bash b/bin-available/start-rtorrent.bash new file mode 100755 index 0000000..70d1848 --- /dev/null +++ b/bin-available/start-rtorrent.bash @@ -0,0 +1,171 @@ +#!/bin/zsh + +## +## This file is part of the `robfrawley/twoface-scripts` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +# +# output line of text +# + +function out { + local context="${1}"; shift + local formats="${1}"; shift + + printf '[%s] (%s) ' "$(date +%s.%N | grep -oE '[0-9]+\.[0-9]{3}')" "${context:l}" + printf "${formats}\n" "${@}" +} + + +# +# output notice line +# + +function out_note { + out note "${@}" +} + + +# +# output failure line +# + +function out_fail { + out fail "${@}" +} + + +# +# output failure line +# + +function out_exit { + local ret="${1}"; shift + + out_fail "${@}" + exit ${ret} +} + +# +# Wait a set amount of time to allow openvpn to start when this is called from screen +# + +function wait { + local seconds=${1} + + if [[ ${seconds} > 0 ]]; then + out_note 'Waiting %f seconds before initiaizlization ...' ${seconds} + sleep ${seconds} + fi +} + + +# +# Resolve the pid of a bash service start script +# + +function resolve_start_script_pid { + local bin="${1}" + + ps aux 2> /dev/null \ + | grep -E "(${bin}|$(basename "${bin}" '.bash'))$" 2> /dev/null \ + | awk '{ print $2 }' 2> /dev/null +} + + +# +# resolve absolute path to bin +# + +function resolve_bin_abs_path { + local bin="${1}" + local nil="${2:-false}" + local abs + + abs="$(which ${bin} 2> /dev/null)" + + [[ $? -eq 0 ]] && [[ -n "${bin}" ]] \ + && echo "${abs}" \ + || echo "${bin}" +} + + +# +# Ensure rtorrent is not running, openvpn is running, and start using any passed options +# + +function init { + local openvpn_bin="$(resolve_bin_abs_path "${1}")" + local openvpn_pid + local torrent_bin="$(resolve_bin_abs_path "${2}")" + local torrent_pid + local torrent_opt + local ip_tun_locl + local ip_tun_extn + local ip_tun_name="${4:-tun0}" + local ip_info_bin="$(resolve_bin_abs_path "ip-info")" + + [[ -z "${torrent_bin}" ]] && torrent_bin="$(resolve_bin_abs_path ${HOME}/rtorrent/start)" + [[ -z "${openvpn_bin}" ]] && openvpn_bin="$(resolve_bin_abs_path start-openvpn)" + + torrent_bin="${HOME}/rtorrent/start" + openvpn_bin="${HOME}/openvpn/bin/start-openvpn" + + if [[ ! -x "${torrent_bin}" ]]; then + out_exit 255 'Configured torrent start script (%s) does not exist or is not executable!' "${torrent_bin}" + fi + + if [[ ! -x "${openvpn_bin}" ]]; then + out_exit 255 'Configured openvpn start script (%s) does not exist or is not executable!' "${openvpn_bin}" + fi + + if [[ ! -x "${ip_info_bin}" ]]; then + out_exit 255 'Configured ip-info command exec (%s) does not exist or is not executable!' "${ip_info_bin}" + fi + + torrent_pid=$(resolve_start_script_pid ${torrent_bin}) + openvpn_pid=$(resolve_start_script_pid ${openvpn_bin}) + + if [[ -n "${torrent_pid}" ]]; then + out_exit 255 'Unable to start rtorrent (%s) as it is already running with PID "%d"!' "${torrent_bin}" "${torrent_pid}" + fi + + if [[ -z "${openvpn_pid}" ]]; then + out_exit 255 'Unable to start rtorrent (%s) as openvpn (%s) is not running!' "${torrent_bin}" "${openvpn_bin}" + fi + + out_note 'Found openvpn exec ("%s") process identifier ("%s") ...' "${openvpn_bin}" "${openvpn_pid}" + + ip_tun_locl="$(${ip_info_bin} -i=${ip_tun_name} -m -q)" + + [[ $? -ne 0 ]] && out_exit 255 'Failed to resolve local ip for "%s" interface using "%s" command.' "${ip_tun_name}" "${ip_info_bin} -i=${ip_tun_name} -m -q" + + ip_tun_extn="$(${ip_info_bin} -i=${ip_tun_name} -m -q -r)" + + [[ $? -ne 0 ]] && out_exit 255 'Failed to resolve remote ip for "%s" interface using "%s" command.' "${ip_tun_name}" "${ip_info_bin} -i=${ip_tun_name} -m -q" + + torrent_opt="${ip_tun_locl}" + + out_note 'Resolved %s interface remote ("%s") and local ("%s") ipv4 addresses ...' "${ip_tun_name}" "${ip_tun_extn}" "${ip_tun_locl}" + out_note 'Invoking rtorrent command ("%s") ...' "${torrent_bin} ${torrent_opt}" + + ${torrent_bin} ${torrent_opt} +} + + +# +# main function +# + +function main { + init "${2:-}" "${3:-}" "${4:-}" +} + +# go! +wait ${1:-180} +main "${@}" diff --git a/bin-available/start-screen-recorder.bash b/bin-available/start-screen-recorder.bash old mode 100644 new mode 100755 diff --git a/bin-available/start-serferals.bash b/bin-available/start-serferals.bash new file mode 100755 index 0000000..987d29f --- /dev/null +++ b/bin-available/start-serferals.bash @@ -0,0 +1,100 @@ +#!/bin/bash + +readonly _SERFERALS_BIN="${HOME}/s/serferals" +readonly _SERFERALS_DEF_PATH_I=('/pool/torrent/_active-user/work/') +readonly _SERFERALS_DEF_PATH_O='/pool/media/video/' + +out_pre() { + local type="${1:-info}" + local char + local code + + case "${type}" in + info) char='--'; code='4'; ;; + asks) char='>>'; code='2'; ;; + warn) char='##'; code='3'; ;; + fail) char='!!'; code='1'; ;; + esac + + printf '\e[38;5;236m(\e[38;5;238m%s\e[38;5;236m@\e[38;5;238m%.04f\e[38;5;236m) \e[97;4%dm %s \e[0m \e[1;9%dm%s\e[0m ' \ + 'serferals' \ + "$(date +%s\.%N)" \ + "${code}" \ + "${type,,}" \ + "${code}" \ + "${char,,}" +} + +ask_confirmation() { + local -a answer_y=(y Y) + local -a answer_n=(n N) + local answer_d="${1:-y}" + local answer_t='' + local question="${2:-do you want to continue}" + local replaces="${@:3}" + + case "${answer_d}" in + y|Y) answer_t=' [Y/n]' ;; + n|N) answer_t=' [y/N]' ;; + esac + + while true; do + out_pre asks + read -n 1 -p "$(printf -- "${question}" "${replaces[@]}")${answer_t}? " answer_u + + [[ "${answer_u}" != '' ]] && printf '\n' + + for a in "${answer_y[@]}"; do + if [[ ${a} == ${answer_u} ]]; then + return 0 + fi + done + + for a in "${answer_n[@]}"; do + if [[ ${a} == ${answer_u} ]]; then + return 1 + fi + done + + if [[ ${answer_u} == '' ]] && ([[ ${answer_d} == 'y' ]] || [[ ${answer_d} == 'Y' ]]); then + return 0 + fi + + out_pre warn + printf 'the provided user response of "%s" is not valid: use only "n" for no and "y" for yes ...\n' "${answer_u}" + done +} + +ask_confirmation y 'are you ready to run serferalls interactively' +printf 'Return code: "%d"\n' "$?" +exit +run_serferals() { + local o="${1}" + local -a i=("${@:2}") + + if [[ ! -e ${_SERFERALS_BIN} ]]; then + printf '[serferals] !! CRIT - Unable to locate an executable serferals binary at "%s" ...' "${b}" + return 255 + fi + + "${_SERFERALS_BIN}" -vvv -s -o "${o}" "${i[@]}" +} + +main() { + while true; do + clear + + printf '\n' + printf '##\n' + printf '## robfrawley/serferals\n' + printf '## interactive prompts for running serferals in a loop\n' + printf '##\n' + printf '\n' + + read -p 'Are you ready to run serferals interactively [(Y)/N]? ' + + read -a _INPUT_PATHS -t 120 -p 'Input files path [/path/to/input/files]: ' + done +} + +main diff --git a/bin-available/start-serferals2.bash b/bin-available/start-serferals2.bash new file mode 100755 index 0000000..de11b78 --- /dev/null +++ b/bin-available/start-serferals2.bash @@ -0,0 +1,201 @@ +#!/bin/bash + +readonly _SERFERALS_BIN="${HOME}/s/serferals" +readonly _SERFERALS_DEF_PATH_I=('/pool/torrent/_active-user/work/') +readonly _SERFERALS_DEF_PATH_O='/pool/media/video/' + +# +# output a compiled text string using a passed format and any number of replacement arguments +# (this function uses a printf-style argument api) +# +out_text() { + printf -- "${@}" +} + +# +# get the output type text for the given output type +# +get_type_iden() { + case "${1:-info}" in + i|I|info|INFO) out_text 'i' ;; + a|A|asks|ASKS) out_text 'a' ;; + w|W|warn|WARN) out_text 'w' ;; + f|F|fail|FAIL) out_text 'f' ;; + c|C|crit|CRIT) out_text 'c' ;; + esac +} + +# +# get the output type text for the given output type +# +get_type_text() { + case "${1:-info}" in + i) out_text 'info' ;; + a) out_text 'asks' ;; + w) out_text 'warn' ;; + f) out_text 'fail' ;; + c) out_text 'crit' ;; + esac +} + +# +# get the output style type text color for the given output type +# +get_type_styr() { + case "${1:-info}" in + i) out_text '1;94' ;; + a) out_text '1;92' ;; + w) out_text '1;93' ;; + f|c) out_text '1;91' ;; + esac +} + +# +# get the output style character for the given output type +# +get_char_text() { + case "${1:-info}" in + i) out_text '--' ;; + a) out_text '>>' ;; + w) out_text '##' ;; + f|c) out_text '!!' ;; + esac +} + +# +# get the output style character color for the given output type +# +get_char_styr() { + case "${1:-info}" in + i) out_text '97;44' ;; + a) out_text '97;42' ;; + w) out_text '97;43' ;; + f|c) out_text '97;41' ;; + esac +} + +# +# output styled text with script name and the current unixtime (with 4-digit nanosecond precision) +# +out_pre() { + local type="${1:-info}" + local char + local code + + case "${type}" in + info) char='--'; code='4'; ;; + asks) char='>>'; code='2'; ;; + warn) char='##'; code='3'; ;; + fail) char='!!'; code='1'; ;; + esac + + out_text '\e[38;5;236m(\e[38;5;238m%s\e[38;5;236m@\e[38;5;238m%.04f\e[38;5;236m) \e[97;4%dm %s \e[0m \e[1;9%dm%s\e[0m ' \ + 'serferals' \ + "$(date +%s\.%N)" \ + "${code}" \ + "${type,,}" \ + "${code}" \ + "${char,,}" +} + +# +# output +# +out_type() { + local type_ident="$()" + local type="${1:-info}" + local char + local code + + case "${type}" in + info) char='--'; code='4'; ;; + asks) char='>>'; code='2'; ;; + warn) char='##'; code='3'; ;; + fail) char='!!'; code='1'; ;; + esac + + out_text '\e[38;5;236m(\e[38;5;238m%s\e[38;5;236m@\e[38;5;238m%.04f\e[38;5;236m) \e[97;4%dm %s \e[0m \e[1;9%dm%s\e[0m ' \ + 'serferals' \ + "$(date +%s\.%N)" \ + "${code}" \ + "${type,,}" \ + "${code}" \ + "${char,,}" +} + +out_line() { + out_type "${1}" + printf -- "${@:2}" +} + +ask_confirmation() { + local -a answer_y=(y Y) + local -a answer_n=(n N) + local answer_d="${1:-y}" + local answer_t='' + local question="${2:-do you want to continue}" + local replaces="${@:3}" + + case "${answer_d}" in + y|Y) answer_t=' [Y/n]' ;; + n|N) answer_t=' [y/N]' ;; + esac + + while true; do + out_type asks + read -n 1 -p "$(printf -- "${question}" "${replaces[@]}")${answer_t}? " answer_u + + [[ "${answer_u}" != '' ]] && printf '\n' + + for a in "${answer_y[@]}"; do + if [[ ${a} == ${answer_u} ]]; then + return 0 + fi + done + + for a in "${answer_n[@]}"; do + if [[ ${a} == ${answer_u} ]]; then + return 1 + fi + done + + if [[ ${answer_u} == '' ]] && ([[ ${answer_d} == 'y' ]] || [[ ${answer_d} == 'Y' ]]); then + return 0 + fi + + out warn 'the provided user response of "%s" is not valid: use only "n" for no and "y" for yes ...\n' "${answer_u}" + done +} + +run_serferals() { + local o="${1}" + local -a i=("${@:2}") + + if [[ ! -e ${_SERFERALS_BIN} ]]; then + out fail 'unable to locate the "serferals" executable file at its expected location of "%s" (ensure it is placed there and then continue here) ...' "${_SERFERALS_BIN}" + return 1 + fi + + "${_SERFERALS_BIN}" -vvv -s -o "${o}" "${i[@]}" + + [[ $? -eq 0 ]] && return 0 || return 1 +} + +main() { + while true; do + clear + + printf '\n' + printf '##\n' + printf '## robfrawley/serferals\n' + printf '## interactive prompts for running serferals in a loop\n' + printf '##\n' + printf '\n' + + read -p 'Are you ready to run serferals interactively [(Y)/N]? ' + + read -a _INPUT_PATHS -t 120 -p 'Input files path [/path/to/input/files]: ' + done +} + +main diff --git a/bin-enabled/blocklist-dl~ b/bin-enabled/blocklist-dl~ new file mode 100755 index 0000000..83b421a --- /dev/null +++ b/bin-enabled/blocklist-dl~ @@ -0,0 +1,240 @@ +#!/bin/bash + +## +## This file is part of the `src-run/user-scripts-server` project. +## +## (c) Rob Frawley 2nd <rmf@src.run> +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +# +# configuration variables +# + +BLOCKLIST_URL_LINK='http://list.iblocklist.com/?list=bt_level2&fileformat=cidr&archiveformat=gz' +BLOCKLIST_EXT_TYPE='cidr' +BLOCKLIST_DIR_BASE='/pool/torrent/blocklist-comprehensive' +BLOCKLIST_OUT_ROOT="${BLOCKLIST_DIR_BASE}/src" +BLOCKLIST_LOG_ROOT="${BLOCKLIST_DIR_BASE}/var" +BLOCKLIST_TMP_ROOT="${BLOCKLIST_DIR_BASE}/tmp" + +# +# internal variables +# + +BLOCKLIST_OUT="${BLOCKLIST_OUT_ROOT}/blocklist.${BLOCKLIST_EXT_TYPE}.txt" +BLOCKLIST_LOG="${BLOCKLIST_LOG_ROOT}/blocklist.${BLOCKLIST_EXT_TYPE}.log" + +function nuller() +{ + local nullable=${1:-$(</dev/stdin)} + + printf '[NULLABLE] => "%s"\n' "${nullable}" +} + +printf 'a fun little error message!' @> >(nuller) +printf 'a fun little error message!' 2>&1 >(nuller) +printf 'a fun little error message!' 1>&2 2> >(nuller) +exit +function fmt_date() +{ + local format="${1}" + + if [[ -n ${format} ]]; then + date +"${format}" 2> /dev/null | awk '{$1=$1};1' 2> /dev/null + + return $? + fi + + return 1 +} + +function get_date() +{ + local detail="${1:-1}" + local f_year='%Y' + local format='%m-%d' + + [[ ${detail} -eq 1 ]] && format="${f_year}:${format}" + + fmt_date "${format}" + + return $? +} + +function get_time() +{ + local detail="${1:-1}" + local format='' + + local f_h_24='%H' + local f_m_24='%M' + local f_s_24='%S' + local f_n_24='%N' + local f_p_24='' + local fmt_24="${f_h_24}:${f_m_24}" + + local f_h_12='%I' + local f_m_12='%M' + local f_s_12='%S' + local f_n_12='%N' + local f_p_12='%p' + local fmt_12="${f_h_12}:${f_m_24}" + + [[ ${detail} -eq 1 ]] && fmt_24="${fmt_24}" + [[ ${detail} -eq 2 ]] && fmt_24="${fmt_24}:${f_s_24}" + [[ ${detail} -eq 3 ]] && fmt_24="${fmt_24}:${f_s_24}.${f_n_24}" + + [[ ${detail} -eq -1 ]] && fmt_12="${fmt_12} ${f_p_12}" + [[ ${detail} -eq -2 ]] && fmt_12="${fmt_12}:${f_s_12} ${f_p_12}" + [[ ${detail} -eq -3 ]] && fmt_12="${fmt_12}:${f_s_12}.${f_n_12} ${f_p_12}" + + if [[ ${detail} -ge 0 ]]; then + format="${fmt_24}" + else + format="${fmt_12}" + fi + + fmt_date "${format}" + + return $? +} + +function get_unix() +{ + local detail="${1:-1}" + local f_nans='%N' + local format="%s" + + [[ ${detail} -eq 1 ]] && format+=".${f_nans}" + [[ ${detail} -eq -1 ]] && format="${f_nans}" + + fmt_date "${format}" + + return $? +} + +printf '[get_date ] => "%s"\n' "$(get_date)" +printf '[get_time ] => "%s"\n' "$(get_time)" +printf '[get_unix ] => "%s"\n' "$(get_unix)" +printf '[get_unix:1] => "%s"\n' "$(get_unix 1)" +printf '[get_unix:1] => "%s"\n' "$(get_unix 0)" + +exit + +#date +%Y-%m-%d\ \@\ %H:%M:%S\ \(%s\.%N\) + +function out_sect() +{ + local format=" [ ${1^^} ] " + shift + + printf "${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" +} + +function out_info() +{ + local format="${1}" + shift + + printf " • ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" +} + +function out_warn() +{ + local format="${1}" + shift + + printf " ! [WARN] ${format}\n" "$@" | tee -a "${BLOCKLIST_LOG}" + + exit 255 +} + +function log_init() +{ + out_sect 'LOG-RUN @ "%s"' "$(date)" + printf '\n[RUN @ "%s"]\n' "$(date)" >> "${BLOCKLIST_LOG}" +} + +function main() +{ + local path="${BLOCKLIST_TMP_ROOT}/blocklist-download-temporary-work" + local file="${path}/$(basename "${BLOCKLIST_OUT}" .txt).gz" + local cust="${1}" + + if [[ "x${cust}" != "xx" ]]; then + BLOCKLIST_OUT="${cust}.${BLOCKLIST_EXT_TYPE}.txt" + BLOCKLIST_LOG="${cust}.${BLOCKLIST_EXT_TYPE}.log" + fi + + local logRoot="$(dirname "${BLOCKLIST_LOG}")" + + if [[ ! -d "${logRoot}" ]]; then + mkdir -p "${logRoot}" + + if [[ $? -ne 0 ]]; then + out_info '[WARNING] Unable to use custom log path: %s' "${BLOCKLIST_LOG}" + + BLOCKLIST_LOG="/tmp/blocklist.${BLOCKLIST_EXT_TYPE}.log" + + out_info '[WARNING] Using system temporary path instead for logs: %s' "${BLOCKLIST_LOG}" + fi + fi + + log_init + out_sect 'Updating blocklist:' "${BLOCKLIST_URL_LINK}" + out_info 'Logged blocklist stat: %s' "${BLOCKLIST_LOG}" + + if [[ ! -d "${path}" ]]; then + mkdir -p "${path}" + + if [[ $? -ne 0 ]]; then + out_warn 'Unable to create temporary working directory "%s"!' "${path}" + fi + fi + + if [[ -f "${file}" ]]; then + rm "${file}" + + if [[ $? -ne 0 ]]; then + out_warn 'Unable to remove old temporary working file "%s"!' "${file}" + fi + fi + + out_info 'Fetch blocklist link: "%s"' "${BLOCKLIST_URL_LINK}" + + wget -q -O "${file}" "${BLOCKLIST_URL_LINK}" + + if [[ $? -ne 0 ]]; then + out_warn 'Unable to download blocklist "%s"!' "${BLOCKLIST_URL_LINK}" + exit + fi + + local size="$(gzip -dc "${file}" | grep -E '^[0-9]' | wc -l)" + + if [[ ${size} -eq 0 ]]; then + out_warn 'Unable to create blocklist as download contains 0 lines!' + exit + fi + + out_info 'Write blocklist file: "%s" (%d lines)' "${BLOCKLIST_OUT}" ${size} + + gzip -dc "${file}" | grep -E '^[0-9]' | sort -u > "${BLOCKLIST_OUT}" + + if [[ $? -ne 0 ]]; then + out_warn 'Unable to parse downloaded blocklist "%s"!' "${path}" + fi + + out_info 'Clean temporary data: "%s"' "${path}" + + rm -fr "${path}" + + if [[ $? -ne 0 ]]; then + out_warn 'Unable to remove temporary working path "%s"!' "${path}" + fi +} + +main "${1:-x}" + diff --git a/bin-enabled/composer-download-global b/bin-enabled/composer-download-global new file mode 120000 index 0000000..18c1d56 --- /dev/null +++ b/bin-enabled/composer-download-global @@ -0,0 +1 @@ +../bin-available/composer-download-global.bash \ No newline at end of file diff --git a/bin-enabled/ip-public-enp7s0 b/bin-enabled/ip-public-enp7s0 new file mode 120000 index 0000000..62102b0 --- /dev/null +++ b/bin-enabled/ip-public-enp7s0 @@ -0,0 +1 @@ +../bin-available/ip-public-enp7s0.bash \ No newline at end of file diff --git a/bin-enabled/magnet-to-torrent-writer b/bin-enabled/magnet-to-torrent-writer deleted file mode 120000 index 1304c2e..0000000 --- a/bin-enabled/magnet-to-torrent-writer +++ /dev/null @@ -1 +0,0 @@ -../bin-available/magnet-to-torrent-writer.py \ No newline at end of file diff --git a/bin-enabled/magnet-to-torrent-writer b/bin-enabled/magnet-to-torrent-writer new file mode 100755 index 0000000..e5d52c7 --- /dev/null +++ b/bin-enabled/magnet-to-torrent-writer @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +''' +Created on Apr 19, 2012 +@author: dan, Faless + GNU GENERAL PUBLIC LICENSE - Version 3 + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + http://www.gnu.org/licenses/gpl-3.0.txt +''' + +import shutil +import tempfile +import os.path as pt +import sys +import libtorrent as lt +from time import sleep +from argparse import ArgumentParser + + +def magnet2torrent(magnet, output_name=None): + if output_name and \ + not pt.isdir(output_name) and \ + not pt.isdir(pt.dirname(pt.abspath(output_name))): + print("Invalid output folder: " + pt.dirname(pt.abspath(output_name))) + print("") + sys.exit(0) + + tempdir = tempfile.mkdtemp() + ses = lt.session() + params = { + 'save_path': tempdir, + 'storage_mode': lt.storage_mode_t(2), + 'paused': False, + 'auto_managed': True, + 'duplicate_is_error': True + } + handle = lt.add_magnet_uri(ses, magnet, params) + + print("Downloading Metadata (this may take a while)") + while (not handle.has_metadata()): + try: + sleep(1) + except KeyboardInterrupt: + print("Aborting...") + ses.pause() + print("Cleanup dir " + tempdir) + shutil.rmtree(tempdir) + sys.exit(0) + ses.pause() + print("Done") + + torinfo = handle.get_torrent_info() + torfile = lt.create_torrent(torinfo) + + output = pt.abspath(torinfo.name() + ".torrent") + + if output_name: + if pt.isdir(output_name): + output = pt.abspath(pt.join( + output_name, torinfo.name() + ".torrent")) + elif pt.isdir(pt.dirname(pt.abspath(output_name))): + output = pt.abspath(output_name) + + print("Saving torrent file here : " + output + " ...") + torcontent = lt.bencode(torfile.generate()) + f = open(output, "wb") + f.write(lt.bencode(torfile.generate())) + f.close() + print("Saved! Cleaning up dir: " + tempdir) + ses.remove_torrent(handle) + shutil.rmtree(tempdir) + + return output + +def main(): + parser = ArgumentParser(description="A command line tool that converts magnet links in to .torrent files") + parser.add_argument('-m','--magnet', help='The magnet url') + parser.add_argument('-o','--output', help='The output torrent file name') + + # + # This second parser is created to force the user to provide + # the 'output' arg if they provide the 'magnet' arg. + # + # The current version of argparse does not have support + # for conditionally required arguments. That is the reason + # for creating the second parser + # + # Side note: one should look into forking argparse and adding this + # feature. + # + conditionally_required_arg_parser = ArgumentParser(description="A command line tool that converts magnet links in to .torrent files") + conditionally_required_arg_parser.add_argument('-m','--magnet', help='The magnet url') + conditionally_required_arg_parser.add_argument('-o','--output', help='The output torrent file name', required=True) + + magnet = None + output_name = None + + # + # Attempting to retrieve args using the new method + # + args = vars(parser.parse_known_args()[0]) + if args['magnet'] is not None: + magnet = args['magnet'] + argsHack = vars(conditionally_required_arg_parser.parse_known_args()[0]) + output_name = argsHack['output'] + if args['output'] is not None and output_name is None: + output_name = args['output'] + if magnet is None: + # + # This is a special case. + # This is when the user provides only the "output" args. + # We're forcing him to provide the 'magnet' args in the new method + # + print ('usage: {0} [-h] [-m MAGNET] -o OUTPUT'.format(sys.argv[0])) + print ('{0}: error: argument -m/--magnet is required'.format(sys.argv[0])) + sys.exit() + # + # Defaulting to the old of doing things + # + if output_name is None and magnet is None: + if len(sys.argv) >= 2: + magnet = sys.argv[1] + if len(sys.argv) >= 3: + output_name = sys.argv[2] + + magnet2torrent(magnet, output_name) + + +if __name__ == "__main__": + main() diff --git a/bin-enabled/mague-args b/bin-enabled/mague-args new file mode 120000 index 0000000..6168d0a --- /dev/null +++ b/bin-enabled/mague-args @@ -0,0 +1 @@ +../bin-available/mague-args.bash \ No newline at end of file diff --git a/bin-enabled/mague-file b/bin-enabled/mague-file new file mode 120000 index 0000000..0c67004 --- /dev/null +++ b/bin-enabled/mague-file @@ -0,0 +1 @@ +../bin-available/mague-file.bash \ No newline at end of file diff --git a/bin-enabled/monitor-torrent-watcher b/bin-enabled/monitor-torrent-watcher new file mode 120000 index 0000000..e42e200 --- /dev/null +++ b/bin-enabled/monitor-torrent-watcher @@ -0,0 +1 @@ +../bin-available/monitor-torrent-watcher.bash \ No newline at end of file diff --git a/bin-enabled/mqueue-args b/bin-enabled/mqueue-args index e485318..543dc4b 120000 --- a/bin-enabled/mqueue-args +++ b/bin-enabled/mqueue-args @@ -1 +1 @@ -magnet-queue \ No newline at end of file +mague-args \ No newline at end of file diff --git a/bin-enabled/mqueue-file b/bin-enabled/mqueue-file index e0b3a36..71d7ce5 120000 --- a/bin-enabled/mqueue-file +++ b/bin-enabled/mqueue-file @@ -1 +1 @@ -magnet-queue-from-file \ No newline at end of file +mague-file \ No newline at end of file diff --git a/bin-enabled/start-openvpn b/bin-enabled/start-openvpn new file mode 120000 index 0000000..e058eeb --- /dev/null +++ b/bin-enabled/start-openvpn @@ -0,0 +1 @@ +/home/rto/openvpn/bin/start-openvpn \ No newline at end of file diff --git a/bin-enabled/start-rtorrent b/bin-enabled/start-rtorrent new file mode 120000 index 0000000..a829122 --- /dev/null +++ b/bin-enabled/start-rtorrent @@ -0,0 +1 @@ +../bin-available/start-rtorrent.bash \ No newline at end of file diff --git a/bin-enabled/start-speedometer b/bin-enabled/start-speedometer new file mode 100755 index 0000000..1a11d86 --- /dev/null +++ b/bin-enabled/start-speedometer @@ -0,0 +1,8 @@ +#!/bin/bash + +SCRIPT_WAIT="${1:-180}" + +printf 'Waiting %d seconds to start...\n' "${SCRIPT_WAIT}" +sleep "${SCRIPT_WAIT}" + +speedometer -k 16 -rx tun0 -tx tun0 -i 0.25 diff --git a/bin-enabled/watch-openvpn b/bin-enabled/watch-openvpn new file mode 120000 index 0000000..3c74e94 --- /dev/null +++ b/bin-enabled/watch-openvpn @@ -0,0 +1 @@ +/home/rto/openvpn/bin/start-openvpn-logtail \ No newline at end of file diff --git a/lib/bashlink b/lib/bashlink new file mode 160000 index 0000000..59ddba0 --- /dev/null +++ b/lib/bashlink @@ -0,0 +1 @@ +Subproject commit 59ddba0e217089aa9ab36d7b8c71318909bcf6a9 diff --git a/lib/bright-library b/lib/bright-library index 5e91878..7f81839 160000 --- a/lib/bright-library +++ b/lib/bright-library @@ -1 +1 @@ -Subproject commit 5e91878d303317be3e474c37cee2aa215825c7d4 +Subproject commit 7f8183907887ac47865c458608819e21df48201c diff --git a/lib/rebash b/lib/rebash new file mode 160000 index 0000000..147b8f6 --- /dev/null +++ b/lib/rebash @@ -0,0 +1 @@ +Subproject commit 147b8f67a229b471179e42759f5ad2790231c0c0 diff --git a/lib/resrc/setup.bash b/lib/resrc/setup.bash new file mode 100755 index 0000000..ec64e2d --- /dev/null +++ b/lib/resrc/setup.bash @@ -0,0 +1,285 @@ +#!/usr/bin/env bash + +## +## This file is part of the `src-run/bash-server-scripts` project. +## +## (c) https://github.com/src-run/bash-server-scripts/graphs/contributors +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +# +# define self script fallback path +# +readonly _RESRC_SELF_PATH_FALLBACK="${0}" + +# +# define self script bash-env path +# +readonly _RESRC_SELF_PATH_BASH_ENV="${BASH_SOURCE[0]}" + +# +# fallback realpath implementation without reliance on realpath or readlink executables +# +# original implementation taken from https://github.com/morgant/realpath by morgan aldridge with +# the following license https://github.com/morgant/realpath#license +# +function _resrc_realpath_fallback() { + local stat_code=0 + local args_path="${1}" + local real_path + local temp_path + local base_file + + # make sure the string isn't empty as that implies something in further logic + if [ -z "${args_path}" ]; then + stat_code=1 + else + # start with the file name (sans the trailing slash) + args_path="${args_path%/}" + + # if we stripped off the trailing slash and were left with nothing, that means we're in the root directory + if [ -z "${args_path}" ]; then + args_path="/" + fi + + # get the basename of the file (ignoring '.' & '..', because they're really part of the path) + base_file="${args_path##*/}" + if [[ ( "${base_file}" = "." ) || ( "${base_file}" = ".." ) ]]; then + base_file="" + fi + + # extracts the directory component of the full path, if it's empty then assume '.' (the current working directory) + temp_path="${args_path%$base_file}" + if [ -z "${temp_path}" ]; then + temp_path='.' + fi + + # attempt to change to the directory + if ! cd "${temp_path}" &> /dev/null; then + stat_code=1 + fi + + if [[ ${stat_code} -ne 1 ]]; then + # does the filename exist? + if [[ ( -n "${base_file}" ) && ( ! -e "${base_file}" ) ]]; then + stat_code=1 + fi + + # get the absolute path of the current directory & change back to previous directory + real_path="$(pwd -P 2> /dev/null)" + cd "-" &> /dev/null + + # Append base filename to absolute path + if [ "${real_path}" = "/" ]; then + real_path="${real_path}${base_file}" + else + real_path="${real_path}/${base_file}" + fi + + # output the absolute path + printf '%s' "${real_path}" + fi + fi + + return ${stat_code} +} + +# +# resolve realpath using the first successful attempt: readlink (executable cmd), realpath (executable cmd), fallback (bash func) +# +function _resrc_realpath() { + local bin_read_link="$( + which readlink 2> /dev/null + )" + local bin_real_path="$( + which realpath 2> /dev/null + )" + local inputted_path="${1}" + local res_temp_path + local resolved_path + + for b in "${bin_read_link}" "${bin_real_path}"; do + if [[ ! -x "${b}" ]]; then + continue; + fi + + res_temp_path="$( + ${b} -m "${inputted_path}" \ + || ${b} "${inputted_path}" + )" + + if [[ -e "${res_temp_path}" ]]; then + resolved_path="${res_temp_path}" + break + fi + done + + printf '%s' "${resolved_path:-$(_resrc_realpath_fallback)}" +} + +# +# resolve real path of this script +# +function _resrc_self_real_path() { + local self_path + + case "$(basename "${SHELL:-sh}")" in + bash) self_path="${_RESRC_SELF_PATH_BASH_ENV}" ;; + * ) self_path="${_RESRC_SELF_PATH_BASH_ENV:-$_RESRC_SELF_PATH_FALLBACK}" ;; + esac + + printf '%s' "$(_resrc_realpath "${self_path}")" +} + +# +# resolve real directory path of this script +# +function _resrc_self_base_path() { + local real_path="$(_resrc_self_real_path)" + + printf '%s' "$(dirname "${real_path}")" +} + +# +# resolve real base file path of this script +# +function _resrc_self_base_file() { + local real_path="$(_resrc_self_real_path)" + + printf '%s' "$(basename "${real_path}")" +} + +# +# define real path of this script +# +readonly _RESRC_SELF_REAL_PATH="$(_resrc_self_real_path)" + +# +# define real base path of this script +# +readonly _RESRC_SELF_BASE_PATH="$(_resrc_self_base_path)" + +# +# define root path of all libraries +# +readonly _LIB_ROOT_PATH="$(_resrc_realpath "${_RESRC_SELF_BASE_PATH}/../")" + +# +# define root path of all modules +# +readonly _MOD_ROOT_PATH="$(_resrc_realpath "${_LIB_ROOT_PATH}/../mod/")" + +# +# define root path of enabled bins +# +readonly _BIN_ENABLED_ROOT_PATH="$(_resrc_realpath "${_LIB_ROOT_PATH}/../bin-enabled/")" + +# +# define root path of available bins +# +readonly _BIN_AVAILABLE_ROOT_PATH="$(_resrc_realpath "${_LIB_ROOT_PATH}/../bin-available/")" + +# +# define root path of rebash library +# +readonly _REBASH_LIB_ROOT_PATH="$(_resrc_realpath "${_LIB_ROOT_PATH}/rebash/")" + +# +# define real path of rebash core module +# +readonly _REBASH_MOD_CORE_PATH="$(_resrc_realpath "${_REBASH_LIB_ROOT_PATH}/core.sh")" + +# +# build internal module paths +# +function _get_mod_abs() { + local in_paths=("${_MOD_ROOT_PATH}" "${_LIB_ROOT_PATH}" "${_BIN_ENABLED_ROOT_PATH}" "${_BIN_AVAILABLE_ROOT_PATH}") + local mod_name="${1}" + local mod_path + local tmp_path + + if [[ -z "${mod_name}" ]]; then + printf 'Failed to build module path (empty mod name provided)...\n' 1>&2 + return 1 + fi + + mod_name="$(basename "${mod_name}" '.bash' 2> /dev/null)" + + for template in "%s" "%s.bash" "%s/%s" "%s/%s.bash"; do + tmp_path="$( + printf "${template}\n" "${mod_name}" "${mod_name}" \ + | head -n1 + )" + + for base_path in "${in_paths[@]}"; do +# printf 'func::%s::%s (%s/%s) [%s]\n' "${FUNCNAME[0]}" "${mod_name}" "${base_path}/${tmp_path}" "${tmp_path}" 1>&2 + if [[ -d "${base_path}" ]] && [[ -f "${base_path}/${tmp_path}" ]]; then + mod_path="$(_resrc_realpath "${base_path}/${tmp_path}")" + break 2 + fi + done + done + + if [[ -z "${mod_path}" ]]; then + printf 'Failed to build module path (unable to find "%s" in paths: %s)...\n' \ + "${mod_name}" \ + "${in_paths[*]}" 1>&2 + fi + + printf '%s' "${mod_path}" +} + +# +# source rebash core module, import rebash logging module, and push debug log entry of success OR write failure message and exit +# +source "${_REBASH_MOD_CORE_PATH}" || (\ + printf \ + 'Failed to locate rebash core module file path (attempted to resolved from "%s" to search path "%s" and failed sourcing at "%s")... Terminating execution.\n' \ + "${_RESRC_SELF_BASE_PATH}" \ + "${_REBASH_LIB_ROOT_PATH}" \ + "${_REBASH_MOD_CORE_PATH}" && \ + exit 255 +) + +# +# import custom rebash logger module +# +core.import "$(_get_mod_abs logger)" + +# +# setup defaul logger levels +# +logging.set_level 'info' +logging.set_commands_level 'info' + +# test timer +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" +#logger.debg 'sleeping for 01.0 seconds...' +#sleep 1 +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" +#logger.debg 'sleeping for 00.7 seconds...' +#sleep .7 +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" +#logger.debg 'sleeping for 04.0 seconds...' +#sleep 4 +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" +#logger.debg 'sleeping for 13.0 seconds...' +#sleep 13 +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" +#logger.debg 'sleeping for 08.0 seconds...' +#sleep 8 +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" +#logger.debg 'sleeping for 99.0 seconds...' +#sleep 99 +#logger.debg 'ran for "%d" milliseconds...' "$(time.timer_get_elapsed)" + +# test logger +#logger.debg 'message with %d replacements for "%s" type' 2 debug +#logger.verb 'message with %d replacements for "%s" type' 2 verbose +#logger.info 'message with %d replacements for "%s" type' 2 informational +#logger.warn 'message with %d replacements for "%s" type' 2 warning +#logger.fail 'message with %d replacements for "%s" type' 2 failure/error +#logger.crit 'message with %d replacements for "%s" type' 2 critical +#logger.exit 'message with %d replacements for "%s" type' 2 exit diff --git a/mod/logger/logger.bash b/mod/logger/logger.bash new file mode 100755 index 0000000..c4d43f3 --- /dev/null +++ b/mod/logger/logger.bash @@ -0,0 +1,367 @@ +#!/usr/bin/env bash + +## +## This file is part of the `src-run/bash-server-scripts` project. +## +## (c) https://github.com/src-run/bash-server-scripts/graphs/contributors +## +## For the full copyright and license information, please view the LICENSE.md +## file that was distributed with this source code. +## + +#=region-init:import + +# import core time module +core.import time + +# start timer +time.timer_start + +# import core ui module +core.import ui + +# configure ui color +([[ "${TERM}" == *"xterm"* ]] || [[ "${TERM}" == *"color"* ]]) \ + && ui.enable_color + +# configure ui glyphs +([[ "${LANG}" == *"UTF-8"* ]]) \ + && ui.enable_unicode_glyphs + +# import core logging module +core.import logging + +# import core array module +core.import array + +#=region-ends:import +#=region-init:docs + +logger__doc__=' + The available log levels are: + error critical warn info debug + The standard loglevel is critical + >>> logger.get_level + >>> logger.get_commands_level + critical + critical + >>> logger.error error-message + >>> logger.critical critical-message + >>> logger.warn warn-message + >>> logger.info info-message + >>> logger.debug debug-message + +doc_test_contains + error-message + critical-message + If the output of commands should be printed, the commands_level needs to be + greater than or equal to the log_level. + >>> logging.set_level critical + >>> logging.set_commands_level debug + >>> echo foo + >>> logging.set_level info + >>> logging.set_commands_level info + >>> echo foo + foo + Another logging prefix can be set by overriding "logging_get_prefix". + >>> logging_get_prefix() { + >>> local level=$1 + >>> echo "[myprefix - ${level}]" + >>> } + >>> logging.critical foo + [myprefix - critical] foo + "logging.plain" can be used to print at any log level and without the + prefix. + >>> logging.set_level critical + >>> logging.set_commands_level debug + >>> logging.plain foo + foo + "logging.cat" can be used to print files (e.g "logging.cat < file.txt") + or heredocs. Like "logging.plain", it also prints at any log level and + without the prefix. + >>> echo foo | logging.cat + foo +' + +#=region-ends:docs +#=region-init:variables + +# decorative logging glyphs array matches the order of logging levels +logger_levels_glyph=( + "${ui_powerline_fail}" + "${ui_powerline_fail}" + "${ui_powerline_fail}" + "${ui_powerline_pointingarrow}" + "${ui_powerline_pointingarrow}" + "${ui_powerline_pointingarrow}" +) + +#=region-ends:variables +#=region-init:functions + +# normalize logger prefix color key +logger_nor_prefix_lev_key() { + local level_key="${1}" + + if [[ ${level_key} -gt ${#logging_levels[@]} ]]; then + level_key=0 + fi + + printf '%d' "${level_key}" +} + +# normalize logger prefix level val +logger_nor_prefix_lev_val() { + local level_val="${1}" + + if ! array.get_index "${level_val}" "${logging_levels[@]}" &> /dev/null; then + level_val="critical" + fi + + printf '%s' "${level_val}" +} + +# get logger prefix reset color +logger_get_prefix_color_res_all() { + printf \ + '%s' \ + "${ui_color_default}${ui_color_nobold}${ui_color_nodim}${ui_color_nounderline}${ui_color_noblink}${ui_color_noinvert}${ui_color_noinvisible}" +} + +# get logger prefix generic dim color +logger_get_prefix_color_gen_dim() { + printf \ + '%s' \ + "${ui_color_darkgray}" +} + +# get logger prefix generic normal color +logger_get_prefix_color_gen_norm() { + printf \ + '%s%s' \ + "${ui_color_gray}" \ + "${ui_color_dim}" +} + +# get logger prefix generic bold color +logger_get_prefix_color_gen_bold() { + printf \ + '%s' \ + "${ui_color_white}" +} + +# get logger prefix level dim color +logger_get_prefix_color_lev_dim() { + local level_key="${1:-info}" + + printf \ + '%s%s' \ + "${logging_levels_color[${level_key}]}" \ + "${ui_color_dim}" +} + +# get logger prefix level normal color +logger_get_prefix_color_lev_norm() { + local level_key="${1:-info}" + + printf \ + '%s' \ + "${logging_levels_color[${level_key}]}" +} + +# get logger prefix level bold color +logger_get_prefix_color_lev_bold() { + local level_key="${1:-info}" + + printf '%s%s' \ + "${logging_levels_color[${level_key}]}" \ + "${ui_color_bold}" +} + +# format prefix elapsed time +logger_format_prefix_elapsed_time() { + local elapse="$(echo "scale=4; $(time.timer_get_elapsed) / 1000" | bc)" + local elaint="$(grep -Eo '^[0-9]+' <<< "${elapse}")" + local offset="${#elaint}" + local format='%%02.03f' + local string="$(printf '%01.04f' "${elapse}")" + local maxlen=6 + + if [[ ${#elaint} -ge $((${maxlen} - 1)) ]]; then + maxlen=$((${#elaint} + 2)) + fi + +# printf '{elapse=%s/elaint=%s/#elaint=%s/format=%s/string=%s/maxlen=%s/string:0:n=%s}' "${elapse}" "${elaint}" "${#elaint}" "${format}" "${string}" "${maxlen}" "${string:0:${maxlen}}" + + printf '%s' "${string:0:${maxlen}}" +} + +# generate logger elapsed time +logger_get_prefix_elapsed_time() { + printf \ + '%s%s%s' \ + "$(logger_get_prefix_color_gen_dim)" \ + "$(logger_format_prefix_elapsed_time)" \ + "$(logger_get_prefix_color_res_all)" +} + +# generate logger prefix script name +logger_get_prefix_scr_name() { + printf \ + '%s%s%s' \ + "$(logger_get_prefix_color_gen_norm)" \ + "$(basename "${BASH_SOURCE[$((${#BASH_SOURCE[@]} - 1))]}")" \ + "$(logger_get_prefix_color_res_all)" +} + +# generate logger prefix datetime component +logger_get_prefix_datetime() { + printf \ + '%s(%s%s%.04f%s%s|%s%s)%s' \ + "$(logger_get_prefix_color_gen_dim)" \ + "$(logger_get_prefix_color_res_all)" \ + "$(logger_get_prefix_color_gen_dim)" \ + "$(date +%s.%N)" \ + "$(logger_get_prefix_color_res_all)" \ + "$(logger_get_prefix_color_gen_dim)" \ + "$(logger_get_prefix_elapsed_time)" \ + "$(logger_get_prefix_color_gen_dim)" \ + "$(logger_get_prefix_color_res_all)" +} + +# generate logger prefix glyph component +logger_get_prefix_glyph() { + local level_key="${1:-info}" + + printf \ + '%s%s%s' \ + "$(logger_get_prefix_color_lev_bold "${level_key}")" \ + "${logger_levels_glyph[${level_key}]}" \ + "$(logger_get_prefix_color_res_all)" +} + +# generate logger prefix line number component +logger_get_prefix_line_number() { + local line_num_key="$((${#BASH_LINENO[@]} - 2))" + + if [[ ${line_num_key} -lt 0 ]]; then + line_num_key=0 + fi + + printf \ + '%d' \ + "${BASH_LINENO[${line_num_key}]}" +} + +# generate logger prefix level component +logger_get_prefix_level() { + local level_val="${1}" + local level_key="${2}" + local line_numb="$(logger_get_prefix_line_number)" + + printf \ + '%s[%s%s%s%s' \ + "$(logger_get_prefix_color_lev_norm "${level_key}")" \ + "$(logger_get_prefix_color_res_all)" \ + "$(logger_get_prefix_color_lev_norm "${level_key}")" \ + "${level_val:0:4}" \ + "$(logger_get_prefix_color_res_all)" + + if [[ -n "${line_numb}" ]]; then + printf \ + '%s:%s%s%05d%s' \ + "$(logger_get_prefix_color_lev_norm "${level_key}")" \ + "$(logger_get_prefix_color_res_all)" \ + "$(logger_get_prefix_color_lev_norm "${level_key}")" \ + "${line_numb}" \ + "$(logger_get_prefix_color_res_all)" + fi + + printf \ + '%s]%s' \ + "$(logger_get_prefix_color_lev_norm "${level_key}")" \ + "$(logger_get_prefix_color_res_all)" +} + +# overwrite rebash base logging prefix function to customize styling +logging_get_prefix() { + local level_val="${1}" + local level_key="$(logger_nor_prefix_lev_key "${2}")" + + printf '%s %s %s %s' \ + "$(logger_get_prefix_datetime)" \ + "$(logger_get_prefix_scr_name)" \ + "$(logger_get_prefix_level "${level_val}" "${level_key}")" \ + "$(logger_get_prefix_glyph "${level_key}")" +} + +# get auto-message text for specific contexts +logger_get_auto_message_text() { + local level_val="${1}" + + case "${level_val}" in + exit) printf -- '(terminating execution due to encountered error)'; return 0 ;; + esac + + return 1 +} + +# normalize user message text +logger_nor_user_text_message() { + local message="${1}" + + printf '%s' "$( + sed -E 's/([^\.])$/\1.../' <<< "${message}" + )" +} + +# log passing context-type followed by printf-type args +logger_log() { + local context="${1}" + local message="${2}" + local replace=("${@:3}") + local add_txt + + message="$(logger_nor_user_text_message "${message}")" + + if add_txt="$(logger_get_auto_message_text "${context}")"; then + message="${message} ${add_txt}" + fi + + local evalstr="logging.$(logger_nor_prefix_lev_val "${context}") \"$( + printf "${message}" "${replace[@]}" 2> /dev/null \ + || printf "${message}" + )\"" + + eval "${evalstr}" + + if [[ ${context} == "exit" ]]; then + exit 255 + fi +} + +#=region-ends:functions +#=region-init:interfaces + +alias logger.text='logger_log' +alias logger.debg='logger_log debug' +alias logger.verb='logger_log verbose' +alias logger.info='logger_log info' +alias logger.warn='logger_log warn' +alias logger.fail='logger_log error' +alias logger.crit='logger_log critical' +alias logger.exit='logger_log exit' +alias logger.set_file_descriptors='logging.set_file_descriptors' +alias logger.set_log_file='logging.set_log_file' +alias logger.set_level='logging.set_level' +alias logger.set_commands_level='logging.set_commands_level' +alias logger.get_level='logging.get_level' +alias logger.get_commands_level='logging.get_commands_level' + +#=region-ends:interfaces +#=region-init:main-sub + +if core.is_main; then + logger.critical 'This script should not be called directly; source this module to use.' +fi + +#=region-ends:main-sub