From be02666464fe8a5d10213a4dcc1db7521373e467 Mon Sep 17 00:00:00 2001 From: Andrew Stowell Date: Fri, 16 May 2025 13:12:29 -0400 Subject: [PATCH] discord.sh now displays to console as well by default, and a lot of cleanup --- .gitignore | 2 +- Discord.ps1 | 115 ---------------------------------- all-crons.sh | 24 ------- colors-discord.sh | 15 +++++ colors.sh => colors-prompt.sh | 0 config.example.ps1 | 12 ---- config.example.sh | 26 +++----- crons/backup-log.sh | 33 ---------- crons/prune-old-backups.sh | 67 -------------------- crons/storage-alert.sh | 28 ++++----- crons/storage-log.sh | 10 +-- crons/thermal-alert.sh | 26 ++++---- crons/thermal-log.sh | 2 +- delay.sh | 8 +-- df-custom.sh | 14 ----- df.sh | 13 ++++ discord.sh | 60 +++++++++++++----- docker-ps.sh | 10 +-- domain-check.sh | 22 +++---- internal/colors.js | 33 ++++++++++ setup/4-notes.sh | 2 + {distinct => unique}/.gitkeep | 0 22 files changed, 171 insertions(+), 351 deletions(-) delete mode 100644 Discord.ps1 delete mode 100755 all-crons.sh create mode 100755 colors-discord.sh rename colors.sh => colors-prompt.sh (100%) delete mode 100644 config.example.ps1 delete mode 100755 crons/backup-log.sh delete mode 100755 crons/prune-old-backups.sh delete mode 100755 df-custom.sh create mode 100755 df.sh create mode 100755 internal/colors.js rename {distinct => unique}/.gitkeep (100%) diff --git a/.gitignore b/.gitignore index b185473..34c5c30 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ /config.sh /Config.ps1 /crons/*.status -/distinct/*.msg +/unique/*.msg /ssh diff --git a/Discord.ps1 b/Discord.ps1 deleted file mode 100644 index c7e8a59..0000000 --- a/Discord.ps1 +++ /dev/null @@ -1,115 +0,0 @@ -############### -# Discord.ps1 # -############### -# -# Windows Powershell Script for logging to Discord using a webhook intergration. -# Just like the bash script, except it will use config.ps1 instead of config.sh. -# Also supports skipping the send if the message is a duplicate. -# -# Script Parameters: -# -message (Pipeline) The message you want to log into discord. -# [-distinct] Optional, distinct name, will skip duplicate messages. -# [-webhook] Optional, Webhook URL, defaults to config. -# [-botName] Optional, Webhook Name, default to config. -# -### Example -# Run from CMD or Batch file to transmit the message to Discord: -# CMD> pwsh -File .\Discord.ps1 -message "Here is some content to send to Discord." -# or pipeline in powershell: -# PS1> echo "Here is some content to send to Discord" | .\Discord.ps1 -# -# You can also pass the "-distinct" option to prevent duplicate messages: -# PS1> echo "same message twice" | .\Discord.ps1 -distinct "my-key" -# # message sent -# PS1> echo "same message twice" | .\Discord.ps1 -distinct "my-key" -# # duplicate message ignored -# - -param ( - [parameter (ValueFromPipeline = $true)] [string[]] $message, - [string] $distinct = "", - [string] $webhook = "", - [string] $botName = "", - [string] $color = "", - [string] $title = "", - [switch] $quiet -) -begin { - $chunk = "" - [string[]] $chunks = New-Object string[] 0 - - # load in defaults from config - $configFile = "$PSScriptRoot\\Config.ps1" - if (Test-Path -Path $configFile) { - . $configFile - - if ( ! $webhook) { - $webhook = $DISCORD_WINDOWS_HOOK - } - if ( ! $botName) { - $botName = $DISCORD_SERVER_NAME - } - if ($title) { - $title = "$title $DISCORD_TITLE_SUFFIX" - } - } - - # load internal function - . "$PSScriptRoot\\SendDiscordChunk.ps1" -} -process { - # build up the full message - foreach ($line in $message) { - if ($chunk.length + $line.length -gt 3600) { - # if adding the line will make it too long, queue existing chunk and reset - $chunks += $chunk - $chunk = "" - } - $chunk += $line + "`n" - } -} -end { - # complete last chunk, by queuing it up - $chunks += $chunk - - # if distinct, load previous message to check for duplicate message - if ($distinct) { - if ( ! $title) { - $title = $distinct; - } - $clean = $distinct -replace '[\.\|\"\*\/\:\<\>\?\\]', ''; - $distinctFile = "$PSScriptRoot\\distinct\\$clean.msg" - if (Test-Path -Path $distinctFile) { - [string[]] $oldMessage = Get-Content -Path $distinctFile - } - } - - $colors = @{ - "maroon" = 6619169; "brown" = 6633216; "olive" = 7238926; "teal" = 168838; "navy" = 70974; "black" = 0; - "red" = 15007744; "orange" = 16347910; "yellow" = 16776980; "lime" = 11206450; "green" = 1421338; - "cyan" = 65535; "blue" = 213983; "purple" = 8265372; "magenta" = 12714104; "grey" = 9606545; - "pink" = 16744896; "apricot" = 16757101; "beige" = 15129254; "mint" = 10485424; "lavender" = 13082607; "white" = 16777215; - }; - - if ($colors.ContainsKey($color)) { - $colorNumber = $colors.$color; - } - - if (($oldMessage -join "`n") -ne ($message -join "`n")) { - # finally send each chunk of the message - foreach ($chunk in $chunks) { - # if quiet flag given, and trimmed content is empty then skip, (normally) otherwise send message - if ($chunk.trim() || ! $quiet) { - SendDiscordMessage -message $chunk -webhook $webhook -botName $botName -title $title -color $colorNumber - } - } - - # if distinct, store the updated message for future checking - if ($distinct) { - Out-File -FilePath $distinctFile -InputObject $message - } - } elseif ($distinct) { - echo "duplicate message" - } -} - diff --git a/all-crons.sh b/all-crons.sh deleted file mode 100755 index ab07dce..0000000 --- a/all-crons.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -# quickly generate a script file which will contain all crontab tasks. -# optionally takes filename to use, defaults to 'crontasks.sh'. -crontasks="$1" - -if [[ -z "$crontasks" ]]; then - crontasks='crontasks.sh' -fi - -# prefix file we are generating -echo "#!/bin/bash" > "$crontasks" -echo "" >> "$crontasks" - -# list crontab, remove comments, convert tabs to space, squeeze the spaces, -# then take the sixth field "command" and add it to the file. -# could have issues if a task has a "#" in the middle. -crontab -l | grep -o '^[^#]*' | tr "\t" ' ' | tr -s ' ' | cut -s -d ' ' -f 6- >> "$crontasks" - -echo "" >> "$crontasks" - -# make the file executable, so we are good to go -chmod +x "$crontasks" - diff --git a/colors-discord.sh b/colors-discord.sh new file mode 100755 index 0000000..0ee1ab1 --- /dev/null +++ b/colors-discord.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +echo 'Color options for discord messaes:' + +echo -e " \e[30m\e[48;2;229;000;000m red \e[m" +echo -e " \e[30m\e[48;2;249;115;006m orange \e[m" +echo -e "\e[37m\e[48;2;101;000;033m maroon \e[m\e[30m\e[48;2;255;255;020m yellow \e[m\e[30m\e[48;2;255;129;192m pink \e[m" +echo -e "\e[37m\e[48;2;101;055;000m brown \e[m\e[30m\e[48;2;170;255;050m lime \e[m\e[30m\e[48;2;255;177;109m apricot \e[m" +echo -e "\e[37m\e[48;2;110;117;014m olive \e[m\e[30m\e[48;2;021;176;026m green \e[m\e[30m\e[48;2;230;218;166m beige \e[m" +echo -e "\e[37m\e[48;2;002;147;134m teal \e[m\e[30m\e[48;2;000;255;255m cyan \e[m\e[30m\e[48;2;159;254;176m mint \e[m" +echo -e "\e[37m\e[48;2;001;021;062m navy \e[m\e[30m\e[48;2;003;067;223m blue \e[m\e[30m\e[48;2;199;159;239m lavender \e[m" +echo -e "\e[37m\e[48;2;000;000;000m black \e[m\e[30m\e[48;2;126;030;156m purple \e[m\e[30m\e[48;2;255;255;255m white \e[m" +echo -e " \e[30m\e[48;2;194;000;120m magenta \e[m" +echo -e " \e[30m\e[48;2;146;149;145m grey \e[m" + diff --git a/colors.sh b/colors-prompt.sh similarity index 100% rename from colors.sh rename to colors-prompt.sh diff --git a/config.example.ps1 b/config.example.ps1 deleted file mode 100644 index df985f6..0000000 --- a/config.example.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -# copy to config.ps1 and update with your information - -$DISCORD_SERVER_NAME = "" - -$DISCORD_TITLE_SUFFIX = "$DISCORD_SERVER_NAME" - -$DISCORD_WINDOWS_HOOK = "?wait=true" - -$DYNV6_ZONE = "" - -$DYNV6_TOKEN = "" - diff --git a/config.example.sh b/config.example.sh index 6c7a190..80df10d 100644 --- a/config.example.sh +++ b/config.example.sh @@ -1,35 +1,29 @@ #!/usr/bin/env bash +# used by crons/thermal-* # degrees in Celsius which we regard as too high THERMAL_ALERT=70 +# used by crons/storage-* STORAGE_MONITOR=("/") +# used by crons/storage-alert.sh # must declare associated array explicitly declare -A STORAGE_ALERT # storage in GiB STORAGE_ALERT=(["/"]=5) -BACKUP_DIRECTORY="/home/ubuntu/data" - -# the directory with backups to cleanup -PRUNE_DIRECTORY="/home/ubuntu/data" - -# what type of backups to cleanup (what to find) "*.zip" etc, or "" -PRUNE_TYPE="" - -# when set to 0, all backups are kept -PRUNE_DOWN_TO=0 - -SERVER_DOMAIN="localhost" +# used by cloudflare.sh, discord.sh +SERVER_DOMAIN=$(cat /etc/hostname) +# used by cloudflare.sh +# default is to only update dns records which have the comment "managed by " CLOUDFLARE_TOKEN="" CLOUDFLARE_ZONE="" CLOUDFLARE_FILTER_PREFIX="comment.contains=managed+by+$SERVER_DOMAIN&" -DISCORD_SERVER_NAME="" - -DISCORD_TITLE_SUFFIX="$DISCORD_SERVER_NAME" - +# used by discord.sh +DISCORD_SERVER_NAME="$SERVER_DOMAIN" +DISCORD_TITLE_SUFFIX="ยท $DISCORD_SERVER_NAME" DISCORD_GENERAL_HOOK="?wait=true" diff --git a/crons/backup-log.sh b/crons/backup-log.sh deleted file mode 100755 index 27c0a02..0000000 --- a/crons/backup-log.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash - -backupDir="$1" -backupType="$2" - -# load in defaults from config -scriptRoot="$(dirname "$0")/.." -configFile="$scriptRoot/config.sh" -if [[ -f "$configFile" ]]; then - source "$configFile" - - if [[ -z "$backupDir" ]]; then - backupDir="$BACKUP_DIRECTORY" - fi - if [[ -z "$backupType" ]]; then - backupType="$PRUNE_TYPE" - fi -fi - -if [[ "$backupType" = "" ]]; then - backups=$(find "$backupDir" -maxdepth 1 -type d | grep -v "^$backupDir$" | sort | xargs du -h --summarize) - hashes="" -else - backups=$(find "$backupDir" -type f -name "$backupType" | sort | xargs du -h) - hashes=$(find "$backupDir" -type f -name "$backupType" | sort | xargs md5sum --tag) -fi - -echo "$backups" -if [[ -n "$hashes" ]]; then - echo "$hashes" -fi -"$scriptRoot/discord.sh" -c "mint" -t "Backup Status" "$backups" "$hashes" - diff --git a/crons/prune-old-backups.sh b/crons/prune-old-backups.sh deleted file mode 100755 index fd17f06..0000000 --- a/crons/prune-old-backups.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash - -# prune the directory of matching files or subfolders, -# until we only have the desired number of backups remaining. -# assumes backups are named with something like datestamp, -# as we want to keep the bottom of the file list wheb sorted. - -# pulls from config, but can take overrides: -# prune-old-backups.sh "where-to-look" "what-to-find" "how-many-to-keep" - -LOCATION=`dirname "$0"` - -source "${LOCATION}/../config.sh" - -# directory to prune -pruneDir="$PRUNE_DIRECTORY" - -# what to prune from that directory -pruneType="$PRUNE_TYPE" - -# how many to keep -keepCount="$PRUNE_DOWN_TO" - -if [ -n "$1" ]; then - pruneDir="$1" -fi - -if [ -n "$2" ]; then - pruneType=""$2 -fi - -if [ -n "$3" ]; then - keepCount="$3" -fi - -if (( "${keepCount}" > "0" )); then - removeCount=0 - - # find direct subfolders to remove - if [ "${pruneType}" = "" ]; then - # notice the grep to remove the pruneDir from the results - # head given a negative number will stop that much short from the bottom, so we keep those matches - while read -r dirToRemove; do - if [ -z "${dirToRemove}" ]; then break; fi - removeCount=$((removeCount+1)) - echo "Removing: ${dirToRemove}" - rm -r "${dirToRemove}" - done <<< `find "${pruneDir}" -maxdepth 1 -type d | grep -v "^${pruneDir}$" | sort | head -n "-${keepCount}"` - else - # head given a negative number will stop that much short from the bottom, so we keep those matches - while read -r fileToRemove; do - if [ -z "${fileToRemove}" ]; then break; fi - removeCount=$((removeCount+1)) - echo "Removing: ${fileToRemove}" - rm "${fileToRemove}" - done <<< `find "${pruneDir}" -type f -name "${pruneType}" | sort | head -n "-${keepCount}"` - fi - - if (( $removeCount > 0 )); then - echo "Successfully removed ${removeCount} extra backups." - else - echo 'Nothing to do, we do not have too many backups.' - fi -else - echo 'Nothing to do, you said keep everything.' -fi - diff --git a/crons/storage-alert.sh b/crons/storage-alert.sh index 375d115..6f69a99 100755 --- a/crons/storage-alert.sh +++ b/crons/storage-alert.sh @@ -4,11 +4,11 @@ locations="$@" # load in defaults from config scriptRoot="$(dirname "$0")/.." -configFile="$scriptRoot/config.sh" -if [[ -f "$configFile" ]]; then - source "$configFile" +configFile="${scriptRoot}/config.sh" +if [[ -f "${configFile}" ]]; then + source "${configFile}" - if [[ -z "$locations" ]]; then + if [[ -z "${locations}" ]]; then locations=${STORAGE_MONITOR[@]} fi fi @@ -16,22 +16,22 @@ fi warn=false messages=() for index in "${!STORAGE_ALERT[@]}"; do - storage=$("$scriptRoot/storage.sh" "$index" "${STORAGE_ALERT[$index]}") + storage=$("${scriptRoot}/storage.sh" "${index}" "${STORAGE_ALERT[$index]}") alert="$?" - if [[ "0" != "$alert" ]]; then + if [[ '0' != "${alert}" ]]; then warn=true - messages+=("$storage is below threshold ${STORAGE_ALERT[$index]}G") + messages+=("${storage} is below threshold ${STORAGE_ALERT[$index]}G") else - messages+=("$storage is above threshold ${STORAGE_ALERT[$index]}G") + messages+=("${storage} is above threshold ${STORAGE_ALERT[$index]}G") fi done -title="Storage Update" -if [[ "$warn" = true ]]; then - purple="purple" - title="Storage Alert" +title='Storage Update' +if [[ "${warn}" = true ]]; then + purple='purple' + title='Storage Alert' fi -printf "%s\n" "${messages[@]}" -printf "%s\n" "${messages[@]}" | "$scriptRoot/discord.sh" -c "${purple-blue}" -d "Storage Alert" -t "$title" +printf "%s\n" "${messages[@]}" | "${scriptRoot}/discord.sh" -c "${purple-blue}" -d 'Storage Alert' -t "${title}" + diff --git a/crons/storage-log.sh b/crons/storage-log.sh index 65520d5..99d5096 100755 --- a/crons/storage-log.sh +++ b/crons/storage-log.sh @@ -4,14 +4,14 @@ locations="$@" # load in defaults from config scriptRoot="$(dirname "$0")/.." -configFile="$scriptRoot/config.sh" -if [[ -f "$configFile" ]]; then - source "$configFile" +configFile="${scriptRoot}/config.sh" +if [[ -f "${configFile}" ]]; then + source "${configFile}" - if [[ -z "$locations" ]]; then + if [[ -z "{$locations}" ]]; then locations=${STORAGE_MONITOR[@]} fi fi -"$scriptRoot/df-custom.sh" $locations | "$scriptRoot/discord.sh" -c "blue" -t "Storage Status" +"${scriptRoot}/df.sh" $locations | "${scriptRoot}/discord.sh" -c 'blue' -t 'Storage Status' diff --git a/crons/thermal-alert.sh b/crons/thermal-alert.sh index a830547..6a07b57 100755 --- a/crons/thermal-alert.sh +++ b/crons/thermal-alert.sh @@ -6,27 +6,27 @@ alertLevel="$1" # load in defaults from config scriptRoot="$(dirname "$0")/.." configFile="$scriptRoot/config.sh" -if [[ -f "$configFile" ]]; then - source "$configFile" +if [[ -f "${configFile}" ]]; then + source "${configFile}" - if [[ -z "$alertLevel" ]]; then - alertLevel="$THERMAL_ALERT" + if [[ -z "${alertLevel}" ]]; then + alertLevel="${THERMAL_ALERT}" fi fi # get current status -thermal=$("$scriptRoot/thermal.sh" "$alertLevel") +thermal=$("$scriptRoot/thermal.sh" "${alertLevel}") alert="$?" -if [[ "0" -ne "$alert" ]]; then +if [[ '0' -ne "${alert}" ]]; then # if currently in an alert status - alertLevelF=`echo "scale=1 ; $alertLevel * 9 / 5 + 32" | bc -l` - "$scriptRoot/discord.sh" -c "red" -t "Thermal Alert" "$thermal" $'\n' "above threshold $alertLevel C ($alertLevelF F)" - touch "$HOME/.thermal.alert" -elif [[ -f "$HOME/.thermal.alert" ]]; then + alertLevelF=$(echo "scale=1 ; ${alertLevel} * 9 / 5 + 32" | bc -l) + "${scriptRoot}/discord.sh" -c red -t 'Thermal Alert' "${thermal}" $'\n' "above threshold ${alertLevel} C (${alertLevelF} F)" + touch "${HOME}/.thermal.alert" +elif [[ -f "${HOME}/.thermal.alert" ]]; then # if previously in an alert status - alertLevelF=`echo "scale=1 ; $alertLevel * 9 / 5 + 32" | bc -l` - "$scriptRoot/discord.sh" -c "orange" -t "Thermal Alert" "$thermal" $'\n' "previously above threshold $alertLevel C ($alertLevelF F)" - rm "$HOME/.thermal.alert" + alertLevelF=$(echo "scale=1 ; ${alertLevel} * 9 / 5 + 32" | bc -l) + "${scriptRoot}/discord.sh" -c orange -t 'Thermal Alert' "${thermal}" $'\n' "previously above threshold ${alertLevel} C (${alertLevelF} F)" + rm "${HOME}/.thermal.alert" fi diff --git a/crons/thermal-log.sh b/crons/thermal-log.sh index 0a42ebc..6d90895 100755 --- a/crons/thermal-log.sh +++ b/crons/thermal-log.sh @@ -2,5 +2,5 @@ scriptRoot="$(dirname "$0")/.." -"$scriptRoot/thermal.sh" | "$scriptRoot/discord.sh" -c "yellow" -t "Thermal Status" +"${scriptRoot}/thermal.sh" | "${scriptRoot}/discord.sh" -c yellow -t 'Thermal Status' diff --git a/delay.sh b/delay.sh index 9256e0b..7a1b65e 100755 --- a/delay.sh +++ b/delay.sh @@ -1,19 +1,19 @@ #!/usr/bin/env bash # optionally takes a single argument of how long of a delay to take. defaults to 5 seconds. -seconds=$1 +seconds="$1" # seconds -if [[ "$seconds" -lt "1" ]] || [[ "$seconds" -gt "60" ]]; then +if [[ "${seconds}" -lt "1" ]] || [[ "${seconds}" -gt "60" ]]; then seconds=5 fi # convert delay in seconds to 1/50 slice of time -slice=$(echo "scale=3; $seconds/50" | bc -l) +slice=$(echo "scale=3; ${seconds}/50" | bc -l) echo '' for i in $(seq 1 50); do - sleep "$slice" + sleep "${slice}" echo -n '.' done echo '' diff --git a/df-custom.sh b/df-custom.sh deleted file mode 100755 index c83a281..0000000 --- a/df-custom.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -LOCATION=`dirname "$0"` - -if (( "0" == "$#" )); then - device="/" - source "${LOCATION}/storage.sh" "$device" - exit -fi - -for device in "$@"; do - source "${LOCATION}/storage.sh" "$device" -done - diff --git a/df.sh b/df.sh new file mode 100755 index 0000000..c175864 --- /dev/null +++ b/df.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +scriptRoot=$(dirname "$0") + +if (( "0" == "$#" )); then + device='/' + "${scriptRoot}/storage.sh" "${device}" +else + for device in "$@"; do + "${scriptRoot}/storage.sh" "${device}" + done +fi + diff --git a/discord.sh b/discord.sh index 182b99d..cb21a22 100755 --- a/discord.sh +++ b/discord.sh @@ -3,12 +3,14 @@ # discord colors are standard 6-digit hex, but converted to a base-10 integer # colors taken from https://xkcd.com/color/rgb/ # and built into a palette based on https://sashamaps.net/docs/resources/20-colors/ +# into my color palette https://color.digitaladapt.com/ # # DARK: maroon(#650021), brown(#653700), olive(#6e750e), teal(#029386), navy(#01153e), black(#000000), # BRIGHT: red(#e50000), orange(#f97306), yellow(#ffff14), lime(#aaff32), green(#15b01a), # cyan(#00ffff), blue(#0343df), purple(#7e1e9c), magenta(#c20078), grey(#929591), # LIGHT: pink(#ff81c0), apricot(#ffb16d), beige(#e6daa6), mint(#9ffeb0), lavender(#c79fef), white(#ffffff). +scriptRoot=$(dirname "$0") quiet=false skipMsg=false declare -A colors @@ -18,13 +20,20 @@ colors=( ["cyan"]=65535 ["blue"]=213983 ["purple"]=8265372 ["magenta"]=12714104 ["grey"]=9606545 ["pink"]=16744896 ["apricot"]=16757101 ["beige"]=15129254 ["mint"]=10485424 ["lavender"]=13082607 ["white"]=16777215 ) +declare -A ansiColors +ansiColors=( + ["maroon"]="\e[37m\e[48;2;101;0;33m" ["brown"]="\e[37m\e[48;2;101;55;0m" ["olive"]="\e[37m\e[48;2;110;117;14m" ["teal"]="\e[37m\e[48;2;2;147;134m" ["navy"]="\e[37m\e[48;2;1;21;62m" ["black"]="\e[37m\e[48;2;0;0;0m" + ["red"]="\e[30m\e[48;2;229;0;0m" ["orange"]="\e[30m\e[48;2;249;115;6m" ["yellow"]="\e[30m\e[48;2;255;255;20m" ["lime"]="\e[30m\e[48;2;170;255;50m" ["green"]="\e[30m\e[48;2;21;176;26m" + ["cyan"]="\e[30m\e[48;2;0;255;255m" ["blue"]="\e[30m\e[48;2;3;67;223m" ["purple"]="\e[30m\e[48;2;126;30;156m" ["magenta"]="\e[30m\e[48;2;194;0;120m" ["grey"]="\e[30m\e[48;2;146;149;145m" + ["pink"]="\e[30m\e[48;2;255;129;192m" ["apricot"]="\e[30m\e[48;2;255;177;109m" ["beige"]="\e[30m\e[48;2;230;218;166m" ["mint"]="\e[30m\e[48;2;159;254;176m" ["lavender"]="\e[30m\e[48;2;199;159;239m" ["white"]="\e[30m\e[48;2;255;255;255m" +) print_usage() { - echo "Usage: $0 [-h hook-url] [-c color] [-d [distinct-name]] [-t title] (message... | -z | < file.msg)" + echo "Usage: $0 [-h hook-url] [-c color] [-d [distinct-name]] [-t title] [-q] (message... | -z | < file.msg)" } # handle all arguments provided -while getopts 'h:c:d:t:zq' flag; do +while getopts ':h:c:d:t:zq' flag; do case "$flag" in h) if [[ "$OPTARG" == "http"*"?wait=true" ]]; then @@ -40,25 +49,29 @@ while getopts 'h:c:d:t:zq' flag; do if [[ -v "colors[$OPTARG]" ]]; then color="$OPTARG" else - echo "Invalid color provided, colors available:" - echo "maroon, brown, olive, teal, navy, black," - echo "red, orange, yellow, lime, green," - echo " cyan, blue, purple, magenta, grey," - echo "pink, apricot, beige, mint, lavender, white." + echo "Invalid color provided" + "${scriptRoot}/colors-discord.sh" print_usage exit 1 fi ;; d) + # whatever the distinct key, we clean it up, since it will be used as a filename + # replace "/" and "|" with "_" + distinct=$(echo "$OPTARG" | sed 's/[\/\|]/_/g') + ;; + :) # '-d' without value is allowed, but generates a warning # in which case we'll use name of parent command with arguments # whatever the distinct key, we clean it up, since it will be used as a filename # replace "/" and "|" with "_" - if [[ -z "$OPTARG" ]]; then + if [[ "$OPTARG" = "d" ]]; then distinct=$(ps -o args= $PPID | sed 's/[\/\|]/_/g') echo "Warning: doing distinct by parent, with key '$distinct'" >&2 else - distinct=$(echo "$OPTARG" | sed 's/[\/\|]/_/g') + echo "option '$OPTARG' provided with value" + print_usage + exit 1 fi ;; t) @@ -81,7 +94,6 @@ done shift "$((OPTIND-1))" # load in defaults from config -scriptRoot=$(dirname "$0") configFile="$scriptRoot/config.sh" if [[ -f "$configFile" ]]; then source "$configFile" @@ -113,6 +125,21 @@ fi message=$(echo "$message" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}') fullMsg="$message" +# output the given message, unless instructed to be quiet +if [[ "$quiet" = false ]]; then + if [[ -n "$distinct" ]] || [[ -n "$title" ]] || [[ -n "$color" ]]; then + if [[ -n "$color" ]]; then + echo -e "${ansiColors[$color]} ${title-$distinct} \e[m" + else + # no color specified, make title bold and underlined + echo -e "\e[1m\e[4m ${title-$distinct} \e[m" + fi + fi + if [[ -n "$fullMsg" ]] && [[ "$skipMsg" = false ]]; then + echo "$fullMsg" + fi +fi + # if message is too long, split it, and after curl, recursively call with remainder # 4k max, but we must account for escaping text in json, so limit to 90% capacity extra="${message:3600}" @@ -153,8 +180,8 @@ fi # handle distinct stuff oldMsg="" if [[ -n "$distinct" ]]; then - if [[ -f "$scriptRoot/distinct/$distinct.msg" ]]; then - oldMsg=$(cat "$scriptRoot/distinct/$distinct.msg") + if [[ -f "$scriptRoot/unique/$distinct.msg" ]]; then + oldMsg=$(cat "$scriptRoot/unique/$distinct.msg") fi if [[ "$fullMsg" = "$oldMsg" ]]; then @@ -162,7 +189,7 @@ if [[ -n "$distinct" ]]; then exit 0 fi - echo "$fullMsg" > "$scriptRoot/distinct/$distinct.msg" + echo "$fullMsg" > "$scriptRoot/unique/$distinct.msg" fi # build content json @@ -185,7 +212,12 @@ fi content="$content}]}" # actually send the message to discord -curl -s -H "Content-Type: application/json" -X POST -d "$content" "$hookUrl" | jq -r '.id,.message' +response=$(curl -s -H "Content-Type: application/json" -X POST -d "$content" "$hookUrl" | jq -r '.message') + +# response message is null unless there was an issue +if [[ "$response" != "null" ]]; then + echo "$response" >&2 +fi # if the message was too long, send along the rest as a separate message if [ -n "$extra" ]; then diff --git a/docker-ps.sh b/docker-ps.sh index 38f5a69..b741b9a 100755 --- a/docker-ps.sh +++ b/docker-ps.sh @@ -1,14 +1,14 @@ #!/usr/bin/env bash # determine if show all or not, default to not -all="" -if [[ "$1" == "-a" ]] || [[ "$1" == "--all" ]]; then - all="--all" +all='' +if [[ "$1" == '-a' ]] || [[ "$1" == '--all' ]]; then + all='--all' fi -if [[ -n `groups | grep 'docker'` ]]; then +if [[ -n $(groups | grep 'docker') ]]; then docker ps $all --format='table {{.Names}}\t{{.Status}}' | grep -v 'NAMES' | sort -elif [[ -n `groups | grep 'sudo'` ]]; then +elif [[ -n $(groups | grep 'sudo') ]]; then sudo docker ps $all --format='table {{.Names}}\t{{.Status}}' | grep -v 'NAMES' | sort else echo 'User lacks docker permission' diff --git a/domain-check.sh b/domain-check.sh index 7485fd1..ef475ca 100755 --- a/domain-check.sh +++ b/domain-check.sh @@ -4,28 +4,24 @@ # check-domain.sh www.example.com [example.org] # check for "-v" in command prompt -VERBOSE=false -while getopts "v" OPTION; do - case $OPTION in +verbose=false +while getopts 'v' flag; do + case "$flag" in v) - VERBOSE=true + verbose=true ;; esac done +shift "$((OPTIND-1))" -if [ "$VERBOSE" = false ]; then - echo "use -v for verbose mode (to also get TTL)" +if [ "$verbose" = false ]; then + echo "use -v for verbose mode (to also get DNS TTL)" fi function process_domain_list () { for domain in "$@"; do - # skip "-v" option if given - if [[ "$domain" == "-v" ]]; then - continue - fi - # get current https status code from this domain - curl -s -o /dev/null --connect-timeout 0.5 -I -w "%{http_code} " "https://$domain/" + curl -s -o /dev/null --connect-timeout 0.5 -I -w '%{http_code} ' "https://$domain/" # we lookup the name-server for the base domain, and use that as our resolver # TODO need to fix, as this will not work with domains like: "example.co.uk" @@ -37,7 +33,7 @@ function process_domain_list () { nameserver=$(dig +short NS $basedomain | head -n 1) # if verbose, we show full answer, instead of just the ip (adds TTL and Record Type) - if [ $VERBOSE = true ]; then + if [ $verbose = true ]; then output=$(dig @$nameserver +noall +answer $domain) printf "%-39.39s %5.5s %-2.2s %-10.10s %-39.39s\n" $output else diff --git a/internal/colors.js b/internal/colors.js new file mode 100755 index 0000000..ed8330e --- /dev/null +++ b/internal/colors.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +/* convert hex to ansi */ +function hexToRGB(color, prefix, name) { + var r = parseInt(color.substring(1, 3), 16); // red + var g = parseInt(color.substring(3, 5), 16); // green + var b = parseInt(color.substring(5, 7), 16); // blue + var d = parseInt(color.substring(1, 7), 16); // discord + return `${prefix}\\e[48;2;${r};${g};${b}m ${name} (${d}) \\e[m`; +} + +console.log(hexToRGB('#650021', '\\e[37m', 'maroon')); +console.log(hexToRGB('#653700', '\\e[37m', 'brown')); +console.log(hexToRGB('#6e750e', '\\e[37m', 'olive')); +console.log(hexToRGB('#029386', '\\e[37m', 'teal')); +console.log(hexToRGB('#01153e', '\\e[37m', 'navy')); +console.log(hexToRGB('#000000', '\\e[37m', 'black')); +console.log(hexToRGB('#e50000', '\\e[30m', 'red')); +console.log(hexToRGB('#f97306', '\\e[30m', 'orange')); +console.log(hexToRGB('#ffff14', '\\e[30m', 'yellow')); +console.log(hexToRGB('#aaff32', '\\e[30m', 'lime')); +console.log(hexToRGB('#15b01a', '\\e[30m', 'green')); +console.log(hexToRGB('#00ffff', '\\e[30m', 'cyan')); +console.log(hexToRGB('#0343df', '\\e[30m', 'blue')); +console.log(hexToRGB('#7e1e9c', '\\e[30m', 'purple')); +console.log(hexToRGB('#c20078', '\\e[30m', 'magenta')); +console.log(hexToRGB('#929591', '\\e[30m', 'grey')); +console.log(hexToRGB('#ff81c0', '\\e[30m', 'pink')); +console.log(hexToRGB('#ffb16d', '\\e[30m', 'apricot')); +console.log(hexToRGB('#e6daa6', '\\e[30m', 'beige')); +console.log(hexToRGB('#9ffeb0', '\\e[30m', 'mint')); +console.log(hexToRGB('#c79fef', '\\e[30m', 'lavender')); +console.log(hexToRGB('#ffffff', '\\e[30m', 'white')); diff --git a/setup/4-notes.sh b/setup/4-notes.sh index 6926729..4c15591 100755 --- a/setup/4-notes.sh +++ b/setup/4-notes.sh @@ -2,4 +2,6 @@ echo 'Next steps:' echo '* get tailscale install script from the website and run it' +echo '* setup config.sh for shell-scripts' +echo '* setup crons for storage and thermal alerts' diff --git a/distinct/.gitkeep b/unique/.gitkeep similarity index 100% rename from distinct/.gitkeep rename to unique/.gitkeep