mirror of
https://github.com/Lissy93/dotfiles.git
synced 2025-01-09 05:38:14 +01:00
Merge pull request #1 from Lissy93/temp-work-in-progress
Temp work in progress
This commit is contained in:
commit
b05a2befc5
@ -3,22 +3,45 @@
|
|||||||
create: true
|
create: true
|
||||||
relink: true
|
relink: true
|
||||||
|
|
||||||
- clean: ['~', '~/.config']
|
- clean: ['~', '${XDG_CONFIG_HOME}']
|
||||||
|
|
||||||
|
- shell:
|
||||||
|
- description: Check that $XDG_CONFIG_HOME is set
|
||||||
|
command: >
|
||||||
|
if [ -z ${XDG_CONFIG_HOME+x} ]; then; \
|
||||||
|
echo "XDG_CONFIG_HOME is not yet set. Will use ~/.config"; \
|
||||||
|
XDG_CONFIG_HOME="${HOME}/.config"; \
|
||||||
|
fi
|
||||||
|
stdin: false
|
||||||
|
stdout: true
|
||||||
|
stderr: true
|
||||||
|
quiet: true
|
||||||
|
- description: Check that $XDG_DATA_HOME is set
|
||||||
|
command: >
|
||||||
|
if [ -z ${XDG_DATA_HOME+x} ]; then; \
|
||||||
|
echo "XDG_DATA_HOME is not yet set. Will use ~/.local/share"; \
|
||||||
|
XDG_DATA_HOME="${HOME}/.local/share"; \
|
||||||
|
fi
|
||||||
|
stdin: false
|
||||||
|
stdout: true
|
||||||
|
stderr: true
|
||||||
|
quiet: true
|
||||||
|
|
||||||
|
|
||||||
- link:
|
- link:
|
||||||
~/.zshenv:
|
~/.zshenv:
|
||||||
path: zsh/.zshenv
|
path: zsh/.zshenv
|
||||||
force: true
|
force: true
|
||||||
~/.config/zsh: zsh
|
${XDG_CONFIG_HOME}/zsh: zsh
|
||||||
~/.config/vim: vim
|
${XDG_CONFIG_HOME}/vim: vim
|
||||||
~/.config/nvim: vim
|
${XDG_CONFIG_HOME}/nvim: vim
|
||||||
~/.config/bash: bash
|
${XDG_CONFIG_HOME}/bash: bash
|
||||||
~/.tmux.conf: tmux/.tmux.conf
|
${XDG_CONFIG_HOME}/tmux/tmux.conf: tmux/tmux.conf
|
||||||
~/.local/share/tmux: tpm
|
${XDG_DATA_HOME}/tmux: tpm
|
||||||
~/.config/utils: utils
|
${XDG_CONFIG_HOME}/utils: utils
|
||||||
~/.gitconfig: configs/.gitconfig
|
~/.gitconfig: configs/.gitconfig
|
||||||
~/.config/.gitignore_global: configs/.gitignore_global
|
${XDG_CONFIG_HOME}/.gitignore_global: configs/.gitignore_global
|
||||||
~/.config/curl/.curlrc: configs/.curlrc
|
# ${XDG_CONFIG_HOME}/curl/.curlrc: configs/.curlrc
|
||||||
~/.Brewfile:
|
~/.Brewfile:
|
||||||
if: '[ `uname` = Darwin ]'
|
if: '[ `uname` = Darwin ]'
|
||||||
path: installs/.Brewfile
|
path: installs/.Brewfile
|
||||||
@ -28,5 +51,8 @@
|
|||||||
~/.finicky.js:
|
~/.finicky.js:
|
||||||
if: '[ `uname` = Darwin ]'
|
if: '[ `uname` = Darwin ]'
|
||||||
path: configs/.finicky.js
|
path: configs/.finicky.js
|
||||||
- shell:
|
|
||||||
- git submodule sync --recursive
|
- create:
|
||||||
|
- ~/Downloads
|
||||||
|
- ~/Documents
|
||||||
|
- ~/Applications
|
||||||
|
65
Dockerfile
Normal file
65
Dockerfile
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
LABEL maintainer "Alicia Sykes <https://aliciasykes.com>"
|
||||||
|
LABEL org.opencontainers.image.source https://github.com/lissy93/dotfiles
|
||||||
|
|
||||||
|
ARG user=alicia
|
||||||
|
ARG group=wheel
|
||||||
|
ARG uid=1000
|
||||||
|
ARG dotfiles=dotfiles.git
|
||||||
|
ARG userspace=userspace.git
|
||||||
|
ARG vcsprovider=github.com
|
||||||
|
ARG vcsowner=lissy93
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
|
||||||
|
apk upgrade --no-cache && \
|
||||||
|
apk add --update --no-cache \
|
||||||
|
sudo \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
libtool \
|
||||||
|
nasm \
|
||||||
|
ncurses \
|
||||||
|
ca-certificates \
|
||||||
|
libressl \
|
||||||
|
bash-completion \
|
||||||
|
cmake \
|
||||||
|
ctags \
|
||||||
|
file \
|
||||||
|
curl \
|
||||||
|
build-base \
|
||||||
|
gcc \
|
||||||
|
coreutils \
|
||||||
|
wget \
|
||||||
|
neovim \
|
||||||
|
git git-doc \
|
||||||
|
zsh \
|
||||||
|
vim \
|
||||||
|
tmux \
|
||||||
|
docker \
|
||||||
|
docker-compose
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
echo "%${group} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers && \
|
||||||
|
adduser -D -G ${group} ${user} && \
|
||||||
|
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
|
||||||
|
|
||||||
|
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 []
|
101
install.sh
101
install.sh
@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
# IMPORTANT: Before running, read through everything, and confirm it's what you want!
|
# IMPORTANT: Before running, read through everything, and confirm it's what you want!
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Configuration Params
|
# Configuration Params
|
||||||
REPO_NAME="Lissy93/Dotfiles"
|
REPO_NAME="Lissy93/Dotfiles"
|
||||||
REPO_PATH="https://github.com/${REPO_NAME}.git"
|
REPO_PATH="https://github.com/${REPO_NAME}.git"
|
||||||
@ -28,6 +26,9 @@ PLAIN_B='\033[1;37m'
|
|||||||
RESET='\033[0m'
|
RESET='\033[0m'
|
||||||
PURPLE='\033[0;35m'
|
PURPLE='\033[0;35m'
|
||||||
|
|
||||||
|
# Other params
|
||||||
|
PROMPT_TIMEOUT=15 # When user is prompted for input, skip after x seconds
|
||||||
|
|
||||||
# Start timer
|
# Start timer
|
||||||
start_time=`date +%s`
|
start_time=`date +%s`
|
||||||
|
|
||||||
@ -87,24 +88,15 @@ function pre_setup_tasks () {
|
|||||||
# Downloads / updates dotfiles and symlinks them
|
# Downloads / updates dotfiles and symlinks them
|
||||||
function setup_dot_files () {
|
function setup_dot_files () {
|
||||||
|
|
||||||
# If ZSH not the default shell, ask user if they'd like to set it
|
|
||||||
if [[ $SHELL != *"zsh"* ]] && command_exists zsh; then
|
|
||||||
read -p "Would you like to set ZSH as your default shell? (y/N)" -n 1 -r
|
|
||||||
echo
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
chsh -s $(which zsh) $USER
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Download / update dotfiles repo with git
|
# Download / update dotfiles repo with git
|
||||||
if [[ ! -d "$DOTFILES_DIR" ]]
|
if [[ ! -d "$DOTFILES_DIR" ]]
|
||||||
then
|
then
|
||||||
echo "${PURPLE}Dotfiles not yet present. Will download ${REPO_NAME} into ${DOTFILES_DIR}"
|
echo -e "${PURPLE}Dotfiles not yet present. Will download ${REPO_NAME} into ${DOTFILES_DIR}${RESET}"
|
||||||
mkdir -p "${DOTFILES_DIR}"
|
mkdir -p "${DOTFILES_DIR}"
|
||||||
git clone --recursive ${REPO_PATH} ${DOTFILES_DIR}
|
git clone --recursive ${REPO_PATH} ${DOTFILES_DIR}
|
||||||
else
|
else
|
||||||
echo -e "${PURPLE}Pulling changes from ${REPO_NAME} into ${DOTFILES_DIR}"
|
echo -e "${PURPLE}Pulling changes from ${REPO_NAME} into ${DOTFILES_DIR}${RESET}"
|
||||||
cd "${DOTFILES_DIR}" && git pull && git submodule update --recursive
|
cd "${DOTFILES_DIR}" && git pull origin master && git submodule update --recursive
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If git clone / pull failed, then exit with error
|
# If git clone / pull failed, then exit with error
|
||||||
@ -116,6 +108,7 @@ function setup_dot_files () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Set up symlinks with dotbot
|
# Set up symlinks with dotbot
|
||||||
|
echo -e "${PURPLE}Setting up Symlinks${RESET}"
|
||||||
cd "${DOTFILES_DIR}"
|
cd "${DOTFILES_DIR}"
|
||||||
git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive
|
git -C "${DOTBOT_DIR}" submodule sync --quiet --recursive
|
||||||
git submodule update --init --recursive "${DOTBOT_DIR}"
|
git submodule update --init --recursive "${DOTBOT_DIR}"
|
||||||
@ -123,35 +116,66 @@ function setup_dot_files () {
|
|||||||
"${DOTFILES_DIR}/${DOTBOT_DIR}/${DOTBOT_BIN}" -d "${DOTFILES_DIR}" -c "${CONFIG}" "${@}"
|
"${DOTFILES_DIR}/${DOTBOT_DIR}/${DOTBOT_BIN}" -d "${DOTFILES_DIR}" -c "${CONFIG}" "${@}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Applies application-specific preferences, and runs some setup tasks
|
||||||
|
function apply_preferences () {
|
||||||
|
|
||||||
|
# If ZSH not the default shell, ask user if they'd like to set it
|
||||||
|
if [[ $SHELL != *"zsh"* ]] && command_exists zsh; then
|
||||||
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)Would you like to set ZSH as your default shell? (y/N)" -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo -e "${PURPLE}Setting ZSH as default shell${RESET}"
|
||||||
|
chsh -s $(which zsh) $USER
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install / update vim plugins with Plug
|
||||||
|
echo -e "${PURPLE}Installing Vim Plugins${RESET}"
|
||||||
|
vim +PlugInstall +qall
|
||||||
|
|
||||||
|
# Install / update Tmux plugins with TPM
|
||||||
|
echo -e "${PURPLE}Installing TMUX Plugins${RESET}"
|
||||||
|
chmod ug+x "${XDG_DATA_HOME}/tmux/tpm"
|
||||||
|
sh "${XDG_DATA_HOME}/tmux/plugins/tpm/bin/install_plugins"
|
||||||
|
|
||||||
|
|
||||||
|
# Install / update ZSH plugins with Antigen
|
||||||
|
echo -e "${PURPLE}Installing ZSH Plugins${RESET}"
|
||||||
|
/bin/zsh -i -c "antigen update && antigen-apply"
|
||||||
|
}
|
||||||
|
|
||||||
# Based on system type, uses appropriate package manager to install / updates apps
|
# Based on system type, uses appropriate package manager to install / updates apps
|
||||||
function install_packages () {
|
function install_packages () {
|
||||||
# Mac OS
|
|
||||||
if [ "$system_type" = "Darwin" ]; then
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)Would you like to install / update system packages? (y/N) " -n 1 -r
|
||||||
# Homebrew not installed, ask user if they'd like to download it now
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
if ! command_exists brew; then
|
echo -e "\n${PURPLE}Skipping package installs${RESET}"
|
||||||
read -p "Would you like to install Homebrew? (y/N)" -n 1 -r
|
return
|
||||||
echo
|
fi
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo -en "🍺 ${YELLOW_B}Installing Homebrew...${RESET}\n"
|
# Mac OS
|
||||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
if [ "$system_type" = "Darwin" ]; then
|
||||||
export PATH=/opt/homebrew/bin:$PATH
|
# Homebrew not installed, ask user if they'd like to download it now
|
||||||
fi
|
if ! command_exists brew; then
|
||||||
fi
|
read -t $PROMPT_TIMEOUT -p "$(echo -e $CYAN_B)Would you like to install Homebrew? (y/N)" -n 1 -r
|
||||||
# Update / Install the Homebrew packages in ~/.Brewfile
|
echo
|
||||||
if command_exists brew && [ -f "$HOME/.Brewfile" ]
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
then
|
echo -en "🍺 ${YELLOW_B}Installing Homebrew...${RESET}\n"
|
||||||
echo -e "${PURPLE}Updating homebrew and packages...${RESET}"
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||||
brew update
|
export PATH=/opt/homebrew/bin:$PATH
|
||||||
brew upgrade
|
|
||||||
BREW_PREFIX=$(brew --prefix)
|
|
||||||
brew bundle --global --file $HOME/.Brewfile
|
|
||||||
brew cleanup
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# Windows (WIP)
|
# Update / Install the Homebrew packages in ~/.Brewfile
|
||||||
if [ "$system_type" = "WindowsNT" ] || [ "$OSTYPE" = "msys" ] || [ "$OSTYPE" = "cygwin" ]; then
|
if command_exists brew && [ -f "$HOME/.Brewfile" ]
|
||||||
"${DOTFILES_DIR}/installs/windows.sh"
|
then
|
||||||
|
echo -e "${PURPLE}Updating homebrew and packages...${RESET}"
|
||||||
|
brew update
|
||||||
|
brew upgrade
|
||||||
|
BREW_PREFIX=$(brew --prefix)
|
||||||
|
brew bundle --global --file $HOME/.Brewfile
|
||||||
|
brew cleanup
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Updates current session, and outputs summary
|
# Updates current session, and outputs summary
|
||||||
@ -168,6 +192,7 @@ function finishing_up () {
|
|||||||
# Begin!
|
# Begin!
|
||||||
pre_setup_tasks # Print start message, and check requirements are met
|
pre_setup_tasks # Print start message, and check requirements are met
|
||||||
setup_dot_files # Clone / updatae dotfiles, and create the symlinks
|
setup_dot_files # Clone / updatae dotfiles, and create the symlinks
|
||||||
|
apply_preferences # Set settings for individual applications
|
||||||
install_packages # Prompt to install / update OS-specific packages
|
install_packages # Prompt to install / update OS-specific packages
|
||||||
finishing_up # Re-source .zshenv, and print summary
|
finishing_up # Re-source .zshenv, and print summary
|
||||||
# All done!
|
# All done!
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
# To copy, left click and drag to highlight text in yellow,
|
# To copy, left click and drag to highlight text in yellow,
|
||||||
# once you release left click yellow text will disappear and will automatically be available in clibboard
|
# once you release left click yellow text will disappear and will automatically be available in clibboard
|
||||||
|
|
||||||
# Use vim keybindings in copy mode
|
# Use vim keybindings in copy mode
|
||||||
setw -g mode-keys vi
|
setw -g mode-keys vi
|
||||||
|
|
||||||
@ -25,6 +26,9 @@ set -g visual-activity on
|
|||||||
# Use wider color pallete
|
# Use wider color pallete
|
||||||
set -g default-terminal screen-256color
|
set -g default-terminal screen-256color
|
||||||
|
|
||||||
|
# Set install location for plugins
|
||||||
|
set-environment -g TMUX_PLUGIN_MANAGER_PATH "${XDG_DATA_HOME}/tmux/plugins"
|
||||||
|
|
||||||
# Install productivity plugins
|
# Install productivity plugins
|
||||||
set -g @plugin 'tmux-plugins/tmux-sessionist' # Easily manage sessions
|
set -g @plugin 'tmux-plugins/tmux-sessionist' # Easily manage sessions
|
||||||
set -g @plugin 'tmux-plugins/tmux-continuum' # Contineous saves environment for next time
|
set -g @plugin 'tmux-plugins/tmux-continuum' # Contineous saves environment for next time
|
||||||
@ -73,4 +77,4 @@ set -g @ram_high_bg_color "#[bg=1]"
|
|||||||
set -g @ram_high_fg_color "#[bg=white]"
|
set -g @ram_high_fg_color "#[bg=white]"
|
||||||
|
|
||||||
# Import TPM
|
# Import TPM
|
||||||
run -b '~/.local/share/tmux/tpm'
|
run "${XDG_DATA_HOME}/tmux/plugins/tpm/tpm"
|
71
utils/death-to-dotfiles.sh
Normal file
71
utils/death-to-dotfiles.sh
Normal file
@ -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
|
20
utils/print-color-map.sh
Normal file
20
utils/print-color-map.sh
Normal file
@ -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
|
200
utils/qr-code.sh
Normal file
200
utils/qr-code.sh
Normal file
@ -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 <<EOF
|
||||||
|
Qrify
|
||||||
|
Description: Converts strings or URLs into a QR code.
|
||||||
|
Usage: qrify [stringtoturnintoqrcode]
|
||||||
|
-m Enable multiline support (feature not working yet)
|
||||||
|
-h Show the help
|
||||||
|
-v Get the tool version
|
||||||
|
-f Store the QR code as a PNG file
|
||||||
|
-d Decode the QR code from a PNG/GIF/JP(E)G file
|
||||||
|
Examples:
|
||||||
|
qrify this is a test string
|
||||||
|
qrify -m two\\\\nlines
|
||||||
|
qrify github.com (no http:// or https://)
|
||||||
|
qrify -f fileoutputName google.com
|
||||||
|
qrify -d fileName.png
|
||||||
|
|
||||||
|
[31mPlease pay attention:[0m
|
||||||
|
This script needs access to an external API.
|
||||||
|
[5m[1mDo not use it to encode sensitive data.[0m
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfiguredClient || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
while getopts "d:f:m:hvu*:" option
|
||||||
|
do
|
||||||
|
case "${option}" in
|
||||||
|
h) usage && exit 0 ;;
|
||||||
|
m) multiline="1" && echo "Error this is not a supported feature yet" && exit 1 ;;
|
||||||
|
f)
|
||||||
|
fileName=$OPTARG
|
||||||
|
#file name is the first argument of the option -f
|
||||||
|
fileoutput="1";;
|
||||||
|
d)
|
||||||
|
fileName=$OPTARG
|
||||||
|
decode="1";;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $# == "0" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
elif [[ $# == "1" ]];then
|
||||||
|
if [[ $1 == "help" || $1 == ":help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
getConfiguredPython || exit 1
|
||||||
|
checkInternet || exit 1
|
||||||
|
input=$(printf '%s ' "$@")
|
||||||
|
makeqr || exit 1
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
getConfiguredPython || exit 1
|
||||||
|
checkInternet || exit 1
|
||||||
|
if [[ $fileoutput == "1" ]]
|
||||||
|
then
|
||||||
|
input=$(printf '%s ' "${@:3}") # first arg is -f, second is the file name, third onwards is the rest of the argument
|
||||||
|
# will have to be changed when implementing multiline QR code
|
||||||
|
makeQRFile || exit 1
|
||||||
|
exit 0
|
||||||
|
elif [[ $decode == "1" ]]
|
||||||
|
then
|
||||||
|
( decodeQR "$fileName" && echo "$data" ) || exit 1
|
||||||
|
exit 0
|
||||||
|
elif [[ $multiline == "0" ]]; then
|
||||||
|
input=$(printf '%s ' "$@")
|
||||||
|
makeqr || exit 1
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
input=$(printf '%s ' "${@:2}")
|
||||||
|
makeMultiLineQr || exit 1 ## if multiline that means a flag existed so start from the second argument
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
315
utils/test.sh
Normal file
315
utils/test.sh
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
SCRIPTNAME="$0"
|
||||||
|
VERSION="0.0.1"
|
||||||
|
SCRIPTS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
|
||||||
|
|
||||||
|
source "$SCRIPTS_DIR/util/base.sh"
|
||||||
|
source "$SCRIPTS_DIR/util/logging.sh"
|
||||||
|
source "$SCRIPTS_DIR/util/config.sh"
|
||||||
|
source "$SCRIPTS_DIR/util/api.sh"
|
||||||
|
source "$SCRIPTS_DIR/util/dns.sh"
|
||||||
|
|
||||||
|
REQUIRES_FUNCS \
|
||||||
|
debug info warn error log_start \
|
||||||
|
config_load_all config_validate \
|
||||||
|
merge_arrays repeated
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
HELP_TEXT="
|
||||||
|
$SCRIPTNAME v$VERSION
|
||||||
|
|
||||||
|
Helper script to update a DNS record on multiple providers.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
$SCRIPTNAME --domain=domain.example.com [--get|--set=value] [...options]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
[domain] The DNS domain you want to get or set (required)
|
||||||
|
|
||||||
|
--domain=example.com Same as passing [domain] directly as an argument
|
||||||
|
-t=|--type=A The DNS record type, e.g. A, CNAME, etc. (A default)
|
||||||
|
|
||||||
|
-g|--get Get the record value (the default)
|
||||||
|
-s=|--set=value Set the record value, e.g. 123.235.324.234 or the
|
||||||
|
special value 'pubip' to use current public ip
|
||||||
|
|
||||||
|
|
||||||
|
-l=|--ttl=n Set the record TTL to n seconds (overrides api default)
|
||||||
|
-p=|--proxied Set the record to be proxied through CDN (Cloudflare only)
|
||||||
|
-a=|--api=cf,do List of DNS providers to use, e.g. all (default) or cf,do
|
||||||
|
-r=|--refresh=n Run continusouly every n seconds in a loop
|
||||||
|
-w=|--timeout=n Wait n seconds before aborting and retrying
|
||||||
|
|
||||||
|
-c=|--config=file Path to a dotenv-formatted config file to load
|
||||||
|
-e=|--config-prefix=X Load config vars with prefix X e.g. X_VERBOSE=1
|
||||||
|
|
||||||
|
-h|--help Show this help message
|
||||||
|
-v|--verbose Show more verbose output
|
||||||
|
-q|--quiet Supress all output except for errors and warnings
|
||||||
|
--color Force showing of colors in the stderr output
|
||||||
|
--nocolor Force hiding of colors in the stderr output
|
||||||
|
--notimestamps Force hiding of timestamps in stderr output
|
||||||
|
--nologlevels Force hiding of log levels in stderr output
|
||||||
|
|
||||||
|
Config: (passed via --config=file or environment variables)
|
||||||
|
DOMAIN=a.example.com Same as --domain option
|
||||||
|
|
||||||
|
|
||||||
|
CF_API_KEY=12345 Clouflare API token: https://dash.cloudflare.com/<account_id>/profile/api-tokens
|
||||||
|
DO_API_KEY=12345 DigitalOcean API token: https://cloud.digitalocean.com/account/api/tokens
|
||||||
|
|
||||||
|
VEBOSE=1 Show debug output [0]/1
|
||||||
|
QUIET=0 Hide info output: [0]/1
|
||||||
|
COLOR=1 Colorize stderr output: [1]/0
|
||||||
|
TIMEOUT=15 Seconds to wait before aborting and retrying
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$SCRIPTNAME abc.example.com
|
||||||
|
$SCRIPTNAME abc.example.com --get --refresh=30
|
||||||
|
$SCRIPTNAME abc.example.com --type=A --set=pubip --ttl=300 --api=digitalocean --config=~/.digitalocean.env
|
||||||
|
$SCRIPTNAME --domain=abc.example.com --type=A --set=1.2.3.4 --api=digitalocean,cloudflare --refresh=30 --config=./secrets.env
|
||||||
|
|
||||||
|
|
||||||
|
"
|
||||||
|
|
||||||
|
### Default Config
|
||||||
|
API_KEY_PLACEHOLDER="set-this-value-in-your-config-file"
|
||||||
|
ALLOWED_APIS='cf,do'
|
||||||
|
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -A DNS_CLI_ARGS=(
|
||||||
|
# Flag Arguments
|
||||||
|
[GET]='-g|--get'
|
||||||
|
[PROXIED]='-p|--proxied'
|
||||||
|
|
||||||
|
# Named Arguments
|
||||||
|
[DOMAIN]='-d|--domain|-d=*|--domain=*'
|
||||||
|
[TYPE]='-t|--type|-t=*|--type=*'
|
||||||
|
[SET]='-s|--set|-s=*|--set=*'
|
||||||
|
[TTL]='-l|-l=*|--ttl|--ttl=*'
|
||||||
|
[API]='-a|-a=*|--api|--api=*'
|
||||||
|
|
||||||
|
# Positional Arguments
|
||||||
|
# [DOMAIN]='*'
|
||||||
|
# [TYPE]='*'
|
||||||
|
# [SET]='*'
|
||||||
|
)
|
||||||
|
merge_arrays CLI_ARGS BASE_CLI_ARGS DNS_CLI_ARGS
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -A DNS_CONFIG_DEFAULTS=(
|
||||||
|
[DOMAIN]=''
|
||||||
|
[TYPE]='A'
|
||||||
|
[GET]=''
|
||||||
|
[SET]=''
|
||||||
|
|
||||||
|
[API]='all'
|
||||||
|
[TTL]='default'
|
||||||
|
[PROXIED]='false'
|
||||||
|
|
||||||
|
[CF_API_KEY]="$API_KEY_PLACEHOLDER"
|
||||||
|
[CF_DEFAULT_TTL]=1
|
||||||
|
|
||||||
|
[DO_API_KEY]="$API_KEY_PLACEHOLDER"
|
||||||
|
[DO_DEFAULT_TTL]=300
|
||||||
|
)
|
||||||
|
merge_arrays CONFIG_DEFAULTS BASE_CONFIG_DEFAULTS DNS_CONFIG_DEFAULTS
|
||||||
|
declare -A CONFIG
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016 disable=SC2034
|
||||||
|
declare -A CONFIG_VALIDATORS=(
|
||||||
|
[DOMAIN]='[[ "${CONFIG[DOMAIN]}" ]]'
|
||||||
|
[TYPE]='[[ "${CONFIG[TYPE]}" ]]'
|
||||||
|
[SET]='validate_set_config'
|
||||||
|
[API]='validate_api_config'
|
||||||
|
)
|
||||||
|
merge_arrays CONFIG_VALIDATORS BASE_CONFIG_VALIDATORS DNS_CONFIG_VALIDATORS
|
||||||
|
|
||||||
|
|
||||||
|
function validate_set_config {
|
||||||
|
if [[ ! "${CONFIG[GET]}" && ! "${CONFIG[SET]}" ]]; then
|
||||||
|
fatal "Missing --get or --set=value argument (pass --help for usage and examples)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${CONFIG[SET]}" && "${CONFIG[TYPE]}" == 'A' ]]; then
|
||||||
|
if ! [[ "${CONFIG[SET]}" == 'pubip' ]] || echo "${CONFIG[SET]}" | grep -q "$IPV4_REGEX"; then
|
||||||
|
error "Invalid value --set=${CONFIG[SET]} must be pubip or an ip address"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate_api_config {
|
||||||
|
local APIS="${CONFIG[API]}"
|
||||||
|
|
||||||
|
for API in ${APIS//,/ }; do
|
||||||
|
case "$API" in
|
||||||
|
'digitalocean'|'do')
|
||||||
|
[[ "${CONFIG[DO_API_KEY]}" == "$API_KEY_PLACEHOLDER" ]] && {
|
||||||
|
error "You must pass your DO_API_KEY via environment variable or --config=file.env (pass --help for more info)."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
'cloudflare'|'cf')
|
||||||
|
[[ "${CONFIG[CF_API_KEY]}" == "$API_KEY_PLACEHOLDER" ]] && {
|
||||||
|
error "You must pass your CF_API_KEY via environment variable or --config=file.env (pass --help for more info)."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
'all')
|
||||||
|
CONFIG[API]="$ALLOWED_APIS"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unrecognized API type '$API'. (must be one or more of: $ALLOWED_APIS)"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### Main Functions
|
||||||
|
|
||||||
|
function get_record {
|
||||||
|
local API="$1" DOMAIN="$2" TYPE="$3"
|
||||||
|
|
||||||
|
|
||||||
|
if [[ "$API" == "do" ]]; then
|
||||||
|
. ./lib/digitalocean.sh
|
||||||
|
elif [[ "$API" == "cf" ]]; then
|
||||||
|
. ./lib/cloudflare.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
dns_get_record "$DOMAIN" "$TYPE"
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_record {
|
||||||
|
local API="$1" DOMAIN="$2" TYPE="$3" VALUE="$4" TTL="$5" PROXIED="$6"
|
||||||
|
|
||||||
|
local VALUE_BEFORE VALUE_AFTER STATUS
|
||||||
|
|
||||||
|
[[ "$VALUE" == "pubip" ]] && VALUE="$(get_public_ip)" # replace pubip with actual ip
|
||||||
|
|
||||||
|
if [[ "$TYPE" == "TXT" ]]; then
|
||||||
|
VALUE="$(echo "$VALUE" | perl -pe 's/\n/\\\n/gm')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$API" == "do" ]]; then
|
||||||
|
. ./lib/digitalocean.sh
|
||||||
|
elif [[ "$API" == "cf" ]]; then
|
||||||
|
. ./lib/cloudflare.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
VALUE_BEFORE="$(
|
||||||
|
dns_get_record \
|
||||||
|
"$DOMAIN" \
|
||||||
|
"$TYPE"
|
||||||
|
)" && STATUS="$?" || STATUS="$?"
|
||||||
|
|
||||||
|
if [[ "$STATUS" == "8" ]]; then
|
||||||
|
warn "$API/$DOMAIN/$TYPE=$VALUE creating new record..."
|
||||||
|
VALUE_AFTER="$(
|
||||||
|
dns_create_record \
|
||||||
|
"$DOMAIN" \
|
||||||
|
"$TYPE" \
|
||||||
|
"$VALUE" \
|
||||||
|
"$TTL" \
|
||||||
|
"$PROXIED"
|
||||||
|
)"
|
||||||
|
elif ((STATUS>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
|
150
utils/weather.sh
Normal file
150
utils/weather.sh
Normal file
@ -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 <<EOF
|
||||||
|
Weather
|
||||||
|
Description: Provides a 3 day forecast on your current location or a specified location.
|
||||||
|
With no flags Weather will default to your current location.
|
||||||
|
Usage: weather or weather [flag] or weather [country] or weather [city] [state]
|
||||||
|
weather [i][M] get weather in imperial units, optional M means windspeed in m/s
|
||||||
|
weather [m][M] get weather in metric units, optional M means windspeed in m/s
|
||||||
|
weather [Moon] grabs the phase of the moon
|
||||||
|
-h Show the help
|
||||||
|
-v Get the tool version
|
||||||
|
Examples:
|
||||||
|
weather
|
||||||
|
weather Paris m
|
||||||
|
weather Tokyo
|
||||||
|
weather Moon
|
||||||
|
weather mM
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfiguredClient || exit 1
|
||||||
|
|
||||||
|
while getopts "uvh" opt; do
|
||||||
|
case "$opt" in
|
||||||
|
\?) echo "Invalid option: -$OPTARG" >&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
|
@ -18,7 +18,6 @@ export PAGER="less"
|
|||||||
## Respect XDG directories
|
## Respect XDG directories
|
||||||
export ADOTDIR="${XDG_CACHE_HOME}/zsh/antigen"
|
export ADOTDIR="${XDG_CACHE_HOME}/zsh/antigen"
|
||||||
export OPENSSL_DIR="/usr/local/ssl"
|
export OPENSSL_DIR="/usr/local/ssl"
|
||||||
export ANTIBODY_HOME=${XDG_DATA_HOME}/antibody
|
|
||||||
export CARGO_HOME="${XDG_DATA_HOME}/cargo"
|
export CARGO_HOME="${XDG_DATA_HOME}/cargo"
|
||||||
export CURL_HOME="${XDG_CONFIG_HOME}/curl"
|
export CURL_HOME="${XDG_CONFIG_HOME}/curl"
|
||||||
export DOCKER_CONFIG="${XDG_CONFIG_HOME}/docker"
|
export DOCKER_CONFIG="${XDG_CONFIG_HOME}/docker"
|
||||||
@ -28,6 +27,7 @@ export LESSHISTFILE="-" # Disable less history.
|
|||||||
export PASSWORD_STORE_DIR="${XDG_DATA_HOME}/pass"
|
export PASSWORD_STORE_DIR="${XDG_DATA_HOME}/pass"
|
||||||
export PIP_CONFIG_FILE="${XDG_CONFIG_HOME}/pip/pip.conf"
|
export PIP_CONFIG_FILE="${XDG_CONFIG_HOME}/pip/pip.conf"
|
||||||
export PIP_LOG_FILE="${XDG_DATA_HOME}/pip/log"
|
export PIP_LOG_FILE="${XDG_DATA_HOME}/pip/log"
|
||||||
|
export TMUX_PLUGIN_MANAGER_PATH="${XDG_DATA_HOME}/tmux/plugins"
|
||||||
export VIMINIT=":source $XDG_CONFIG_HOME/vim/vimrc"
|
export VIMINIT=":source $XDG_CONFIG_HOME/vim/vimrc"
|
||||||
export WGETRC="${XDG_CONFIG_HOME}/wget/wgetrc"
|
export WGETRC="${XDG_CONFIG_HOME}/wget/wgetrc"
|
||||||
export XINITRC="${XDG_CONFIG_HOME}/X11/xinitrc"
|
export XINITRC="${XDG_CONFIG_HOME}/X11/xinitrc"
|
||||||
|
Loading…
Reference in New Issue
Block a user