From 15225ea137d9c48a412205504a01504400caad20 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 19 Aug 2022 10:05:58 +0100 Subject: [PATCH] work in progress --- Dockerfile | 16 +- utils/death-to-dotfiles.sh | 71 +++++++++ utils/print-color-map.sh | 20 +++ utils/qr-code.sh | 200 +++++++++++++++++++++++ utils/test.sh | 315 +++++++++++++++++++++++++++++++++++++ utils/weather.sh | 150 ++++++++++++++++++ 6 files changed, 766 insertions(+), 6 deletions(-) create mode 100644 utils/death-to-dotfiles.sh create mode 100644 utils/print-color-map.sh create mode 100644 utils/qr-code.sh create mode 100644 utils/test.sh create mode 100644 utils/weather.sh diff --git a/Dockerfile b/Dockerfile index ad39f83..0bcfaa2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,6 +37,8 @@ RUN \ neovim \ git git-doc \ zsh \ + vim \ + tmux \ docker \ docker-compose @@ -46,16 +48,18 @@ RUN \ addgroup ${user} docker COPY ./ /home/${user}/.userspace/ + RUN \ git clone --recursive https://${vcsprovider}/${vcsowner}/${dotfiles} /home/${user}/.dotfiles && \ chown -R ${user}:${group} /home/${user}/.dotfiles && \ chown -R ${user}:${group} /home/${user}/.userspace - # For advanced configuration where you would do ssh-agent and gpg-agent passthrough - # cd /home/${user}/.userspace && \ - # git remote set-url origin git@${vcsprovider}:${vcsowner}/${userspace} && \ - # cd /home/${user}/.dotfiles && \ - # git remote set-url origin git@${vcsprovider}:${vcsowner}/${dotfiles} -ENV HISTFILE=/config/.history +RUN chmod u+x /home/${user}/.dotfiles/install.sh + +USER ${user} + +RUN cd $HOME/.dotfiles && ./install.sh + +ENV HISTFILE=/home/${user}/.cache/.zsh_history CMD [] diff --git a/utils/death-to-dotfiles.sh b/utils/death-to-dotfiles.sh new file mode 100644 index 0000000..f490181 --- /dev/null +++ b/utils/death-to-dotfiles.sh @@ -0,0 +1,71 @@ +#!/bin/sh - +# Quick utility to aid in keeping clutter down in the $HOME directory +# Lists statistics about number of files, auto-cleans certain files, +# and prompts user wheather they'd like to each remaining dotfile in turn + +set -u + +readonly HOME=${HOME:-$(getent passwd "$(id -un)" | cut -d : -f 6)} + +inlist() { +for e in $2; do + case "$1" in ($e) + return + esac +done +false +} + +die() { + retval=$(($1)); shift + { printf "$@"; echo; } >&2 + exit $retval +} + +prompt_delete() { + printf '\nDelete %s? [Y/n] ' "$1" + read -r a + test -t 0 || printf '\033[1;32m%s\033[0m\n' "$a" + case "$a" in + (''|Y*|y*) rm -rv "$1" ;; + (N*|n*) ;; + (*) prompt_delete "$1" ;; + esac +} + +# gather and show statistics: +n_nondots=$(find "$HOME" -maxdepth 1 -mindepth 1 -name '[^.]*' | wc -l) +n_dots=$(find "$HOME" -maxdepth 1 -mindepth 1 -name '.*' | wc -l) +n_all=$((n_nondots + n_dots)) +cat <<- EOF +total: $n_all +normal files: $n_nondots +$(printf '\033[1m')dotfiles: $n_dots$(printf '\033[0m') + +EOF + +# List dotfiles: +cd "$HOME" || die 1 'Could not cd into home directory (%s)' "$HOME" +if ! ls -1d --color=auto .[!.]*; then + die 1 'Could not list files in home directory (%s)' "$HOME" +fi + +# Automatic decisions for specific files/directories: +keeplist='.anthy .local .pam_environment .pki .ssh' +deletelist='.ansible .ansible_galaxy .mozilla .w3m .*_history' + +# delete: +for d in .*; do + case "$d" in (.|..) continue ;; esac + if inlist "$d" "$keeplist"; then + # Do not delete this file + continue + elif inlist "$d" "$deletelist"; then + # Delete this file without asking + echo y | prompt_delete "$d" + continue + else + # Ask the user if should delete or not + prompt_delete "$d" + fi +done \ No newline at end of file diff --git a/utils/print-color-map.sh b/utils/print-color-map.sh new file mode 100644 index 0000000..98edd9b --- /dev/null +++ b/utils/print-color-map.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Prints each foreground and background color using standard 16-bit pallete +# Based on: https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html + +T='Hi!' # The test text + +echo -e "\n \t\t40m\t 41m\t 42m\t 43m\t 44m\t 45m\t 46m\t 47m"; + +for FGs in ' m' ' 1m' ' 30m' '1;30m' ' 31m' '1;31m' ' 32m' \ + '1;32m' ' 33m' '1;33m' ' 34m' '1;34m' ' 35m' '1;35m' \ + ' 36m' '1;36m' ' 37m' '1;37m'; + do FG=${FGs// /} + echo -en " $FGs \033[$FG $T " + for BG in 40m 41m 42m 43m 44m 45m 46m 47m; + do echo -en "$EINS \033[$FG\033[$BG $T \033[0m"; + done + echo; +done +echo diff --git a/utils/qr-code.sh b/utils/qr-code.sh new file mode 100644 index 0000000..79923bd --- /dev/null +++ b/utils/qr-code.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +# Based on similar script by Linyos Torovoltos and Alex Epstein + +multiline="0" # flag that indicates multiline option +fileoutput="0" # flag indicating the -f option + + +# Determine which HTTP GET tool installed +getConfiguredClient () { + if command -v curl &>/dev/null; then + configuredClient="curl" + elif command -v wget &>/dev/null; then + configuredClient="wget" + elif command -v http &>/dev/null; then + configuredClient="httpie" + elif command -v fetch &>/dev/null; then + configuredClient="fetch" + else + echo "Error: This tool requires either curl, wget, httpie or fetch to be installed." >&2 + return 1 + fi +} + +# Call appropriate http get method +httpGet() { + case "$configuredClient" in + curl) curl -A curl -s "$@" ;; + wget) wget -qO- "$@" ;; + httpie) http -b GET "$@" ;; + fetch) fetch -q "$@" ;; + esac +} + +# Get installed version of Python / show error if none +getConfiguredPython() { + if command -v python3 &>/dev/null; then + configuredPython="python3" + elif command -v python2 &>/dev/null; then + configuredPython="python2" + elif command -v python &>/dev/null; then + configuredPython="python" + else + echo "Error: This tool requires python to be installed." + return 1 + fi +} + +if [[ $(uname) != "Darwin" ]]; then + python() { + case "$configuredPython" in + python3) python3 "$@" ;; + python2) python2 "$@" ;; + python) python "$@" ;; + esac + } +fi + +# Encode input, and call to qrenco.de to get response +makeqr() { + input=$(echo "$input" | sed s/" "/%20/g ) ## replace all spaces in the sentence with HTML-encoded space %20 + httpGet qrenco.de/"$input" ## get a response for the qrcode +} + +# Redirects returned QR impage into a png file +makeQRFile() { + input=$(echo "$input" | sed -e s/" "/%20/g -e s/'\\n'/%0A/g ) ##same as in the makeqr function + addFileExt + httpGet "api.qrserver.com/v1/create-qr-code/?size=150x150&data=$input" > "$fileName" +} + +# If filename doesn't already have .png extension, append it +addFileExt() { + if ! echo "$fileName" | grep -E -q ".*\.png$|.*\.PNG$" + then + fileName="$fileName.png" + fi +} + +makeMultiLineQr() { + if [[ ${configuredClient} != "curl" ]]; then ## prevent usage without curl it is unreliable + echo "Multiline currently only supports curl!" + return 1 + else + input=$(echo "$input" | sed -e s/" "/%20/g -e s/'\\n'/%0A/g ) ##same as in the makeqr function + printf "%s" "$input" | curl -F-=\<- qrenco.de + fi +} + +# Function to get the json response from POST request +decodeQR() { + local qrFile="$1" + if ! echo "$fileName" | grep -E -q ".*\.png$|.*\.PNG$|.*\.gif$|.*\.jpg$|.*\.jpeg$|.*\.GIF$|.*\.JPG$|.*\.JPEG$" + then + exit 1 + fi + + # only uses curl + # Cannot use wget because it does not support multipart/form-data (as per the man page)] + + case "$configuredClient" in + curl) JSONresponse=$(curl -s -F "file=@$qrFile" http://api.qrserver.com/v1/read-qr-code/) || exit 1;; + wget) echo "Error:-Not supported with wget" >&2 && exit 1;; + httpie) JSONresponse=$(http -b --form POST http://api.qrserver.com/v1/read-qr-code/ file@"$qrFile") || exit 1;; + fetch) echo "Error:-Not supported with wget" >&2 && exit 1;; + esac + + error="$(echo "$JSONresponse" | python -c "from __future__ import print_function; import sys, json; print(json.load(sys.stdin)[0]['symbol'][0]['error'])")" + + if [[ "$error" == "None" ]] + then + data="$(echo "$JSONresponse" | python -c "from __future__ import print_function; import sys, json; print(json.load(sys.stdin)[0]['symbol'][0]['data'])")" + else + echo "Error:-$error" >&2 && exit 1 + fi +} + +checkInternet() +{ + httpGet github.com > /dev/null 2>&1 || { echo "Error: no active internet connection" >&2; return 1; } # query github with a get request +} + +usage() +{ + cat <0)); then + fatal --status=$STATUS "dns_get_record return an invalid exit status $STATUS" + elif [[ "$VALUE_BEFORE" == "$VALUE" ]]; then + info "$API/$DOMAIN/$TYPE=$VALUE_BEFORE is up-to-date." + return 0 + else + info "$API/$DOMAIN/$TYPE=$VALUE_BEFORE updating to $VALUE..." + + VALUE_AFTER="$( + dns_set_record \ + "$DOMAIN" \ + "$TYPE" \ + "$VALUE" \ + "$TTL" \ + "$PROXIED" + )" + fi + + if ! [[ "$VALUE_AFTER" == "$VALUE" || "$VALUE_AFTER" == "${VALUE}." ]]; then + error "$API/$DOMAIN/$TYPE=$VALUE update failed (got ${VALUE_AFTER:-API error})." + return 1 + else + info "$API/$DOMAIN/$TYPE=$VALUE update succeeded." + return 0 + fi +} + +function log_start_dns { + config_assert INTERVAL API DOMAIN TYPE + + local INTERVAL_STR + + # Begin check/update process + ((CONFIG[INTERVAL]>0)) && INTERVAL_STR="every ${CONFIG[INTERVAL]}s" || INTERVAL_STR="once" + if [[ "${CONFIG[SET]}" ]]; then + info "Starting: SET ${CONFIG[API]}/${CONFIG[DOMAIN]}/${CONFIG[TYPE]}=${CONFIG[SET]} $INTERVAL_STR..." + else + info "Starting: GET ${CONFIG[API]}/${CONFIG[DOMAIN]}/${CONFIG[TYPE]} $INTERVAL_STR..." + fi +} + +function runloop { + local APIS="${CONFIG[API]}" + + GET="${CONFIG[GET]}" + SET="${CONFIG[SET]}" + + for API in ${APIS//,/ }; do + if ((GET==1)); then + timed "${CONFIG[TIMEOUT]}" \ + get_record \ + "$API" \ + "${CONFIG[DOMAIN]}" \ + "${CONFIG[TYPE]}" + return $? + elif [[ "$SET" ]]; then + timed "${CONFIG[TIMEOUT]}" \ + update_record \ + "$API" \ + "${CONFIG[DOMAIN]}" \ + "${CONFIG[TYPE]}" \ + "${CONFIG[SET]}" \ + "${CONFIG[TTL]}" \ + "${CONFIG[PROXIED]}" + return $? + else + fatal 'You must pass either --get or --set=value' + fi + done +} + + +function main { + # Load config from file, env variables, and kwargs + config_load_all CONFIG_DEFAULTS CLI_ARGS "$@" + config_validate CONFIG_VALIDATORS + log_start_dns + + repeated "${CONFIG[INTERVAL]}" runloop +} + +main "$@" +#wait "$!" && STATUS=$? || STATUS=$? +#jobs -p >/dev/null 2>&1 +#jobs -p | xargs 'kill -9 --' >/dev/null 2>&1 + +#if ((STATUS>125)); then + # codes >= 125 are used by the shell only and cannot be returned from scripts + # https://www.tldp.org/LDP/abs/html/exitcodes.html +# exit $((STATUS-100)) +#else +# exit $STATUS +#fi diff --git a/utils/weather.sh b/utils/weather.sh new file mode 100644 index 0000000..4482fdc --- /dev/null +++ b/utils/weather.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash +# Author: Alexander Epstein https://github.com/alexanderepstein + +currentVersion="1.23.0" #This version variable should not have a v but should contain all other characters ex Github release tag is v1.2.4 currentVersion is 1.2.4 +LANG="${LANG:-en}" +locale=$(echo "$LANG" | cut -c1-2) +unset configuredClient +if [[ $(echo "$locale" | grep -Eo "[a-z A-Z]*" | wc -c) != 3 ]]; then locale="en"; fi + +## This function determines which http get tool the system has installed and returns an error if there isnt one +getConfiguredClient() +{ + if command -v curl &>/dev/null; then + configuredClient="curl" + elif command -v wget &>/dev/null; then + configuredClient="wget" + elif command -v http &>/dev/null; then + configuredClient="httpie" + elif command -v fetch &>/dev/null; then + configuredClient="fetch" + else + echo "Error: This tool requires either curl, wget, httpie or fetch to be installed\." >&2 + return 1 + fi +} + +## Allows to call the users configured client without if statements everywhere +httpGet() +{ + case "$configuredClient" in + curl) curl -A curl -s "$@" ;; + wget) wget -qO- "$@" ;; + httpie) http -b GET "$@" ;; + fetch) fetch -q "$@" ;; + esac +} + +getIPWeather() +{ + country=$(httpGet ipinfo.io/country) > /dev/null ## grab the country + if [[ $country == "US" ]]; then ## if were in the us id rather not use longitude and latitude so the output is nicer + city=$(httpGet ipinfo.io/city) > /dev/null + region=$(httpGet ipinfo.io/region) > /dev/null + if [[ $(echo "$region" | wc -w) == 2 ]];then + region=$(echo "$region" | grep -Eo "[A-Z]*" | tr -d "[:space:]") + fi + httpGet $locale.wttr.in/"$city","$region""$1" + else ## otherwise we are going to use longitude and latitude + location=$(httpGet ipinfo.io/loc) > /dev/null + httpGet $locale.wttr.in/"$location""$1" + fi +} + +getLocationWeather() +{ + args=$(echo "$@" | tr " " + ) + httpGet $locale.wttr.in/"${args}" +} + +checkInternet() +{ + httpGet github.com > /dev/null 2>&1 || { echo "Error: no active internet connection" >&2; return 1; } # query github with a get request +} + +usage() +{ + cat <&2 + exit 1 + ;; + h) usage + exit 0 + ;; + v) echo "Version $currentVersion" + exit 0 + ;; + u) checkInternet || exit 1 # check if we have a valid internet connection if this isnt true the rest of the script will not work so stop here + update || exit 1 + exit 0 + ;; + :) echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +if [[ $# == "0" ]]; then + checkInternet || exit 1 + getIPWeather || exit 1 + exit 0 +elif [[ $1 == "help" || $1 == ":help" ]]; then + usage + exit 0 +elif [[ $1 == "update" ]]; then + checkInternet || exit 1 + update || exit 1 + exit 0 +fi + +checkInternet || exit 1 +if [[ $1 == "m" ]]; then + getIPWeather "?m" || exit 1 +elif [[ "${@: -1}" == "m" ]];then + args=$( echo "${@:1:(($# - 1))}" ?m | sed s/" "//g) + getLocationWeather "$args" || exit 1 +elif [[ $1 == "M" ]]; then + getIPWeather "?M" || exit 1 +elif [[ "${@: -1}" == "M" ]];then + args=$( echo "${@:1:(($# - 1))}" ?M | sed s/" "//g) + getLocationWeather "$args" || exit 1 +elif [[ $1 == "mM" || $1 == "Mm" ]]; then + getIPWeather "?m?M" || exit 1 +elif [[ "${@: -1}" == "mM" || "${@:-1}" == "Mm" ]];then + args=$( echo "${@:1:(($# - 1))}" ?m?M | sed s/" "//g) + getLocationWeather "$args" || exit 1 +elif [[ $1 == "iM" || $1 == "Mi" ]]; then + getIPWeather "?u?M" || exit 1 +elif [[ "${@: -1}" == "iM" || "${@:-1}" == "Mi" ]];then + args=$( echo "${@:1:(($# - 1))}" ?u?M | sed s/" "//g) + getLocationWeather "$args" || exit 1 +elif [[ $1 == "i" ]]; then + getIPWeather "?u" || exit 1 +elif [[ "${@: -1}" == "i" ]];then + args=$( echo "${@:1:(($# - 1))}" ?u | sed s/" "//g) + getLocationWeather "$args" || exit 1 +else + getLocationWeather "$@" || exit 1 +fi \ No newline at end of file