#
# good guide to some of its basic features is the readme file
# https://github.com/junegunn/fzf
-if [[ -s /usr/share/doc/fzf/examples/key-bindings.bash ]]; then
- source /usr/share/doc/fzf/examples/key-bindings.bash
-fi
+
+# if [[ -s /usr/share/doc/fzf/examples/key-bindings.bash ]]; then
+# source /usr/share/doc/fzf/examples/key-bindings.bash
+# fi
# * functions
diff -u /tmp/digdiff <(digsort $s2 "$@")
}
+# date in a format i like reading
dt() {
date "+%A, %B %d, %r" "$@"
}
dtr() {
date -R "$@"
}
-ccomp date dt dtr
+# date with all digits in a format i like
+dtd() {
+ date +%F_%T% "$@"
+}
+ccomp date dt dtr dtd
dus() { # du, sorted, default arg of
du -sh ${@:-*} | sort -h
egrinid() {
sed -rn '/testignore|jtuttle|eximbackup/!s/^[^ ]+ ([^ ]+) [^ ]+ [^ ]+ <= ([^ ]+).* id=([^ ]+) T="(.*)" from (<[^ ]+> .*$)/\1 \5\n \3\n \4/p' <${1:-/var/log/exim4/mainlog}
}
+etailin() {
+ tail -F /var/log/exim4/mainlog | sed -rn '/testignore|jtuttle|eximbackup/!s/^[^ ]+ ([^ ]+) [^ ]+ [^ ]+ <= ([^ ]+).*T="(.*)" from (<[^ ]+> .*$)/\1 \4\n \3/p'
+}
ffmpeg -f concat -safe 0 -i $tmpf -c copy "$1"
rm $tmpf
}
+ffremux() {
+ local tmpf tmpd
+ if (( $# == 0 )); then
+ echo ffremux error expected args >&2
+ return 1
+ fi
+ tmpd=$(mktemp -d)
+ for f; do
+ tmpf=$tmpd/"${f##*/}"
+ ffmpeg -i "$f" -c:v copy -c:a copy $tmpf
+ cat $tmpf >"$f"
+ done
+ rm -r $tmpd
+}
+
+
-# full path without resolving symlinks
+# absolute path of file/dir without resolving symlinks.
+#
+# This is what realpath -s does in most cases, but sometimes it
+# actually resolves symlinks, at least when they are in /.
+#
+# Note, if run on a dir, if the final component is relative, it won't
+# resolve that. Use the below fpd for that.
+#
+# note: we could make a variation of this which
+# assigns to a variable name using eval, so that we don't have to do
+# x=$(fp somepath), which might save subshell overhead and look nice,
+# but I'm not going to bother.
fp() {
- local dir base
- base="${1##*/}"
- dir="${1%$base}"
- printf "%s/%s\n" $(cd $dir; pwd) "$base"
+ local initial_oldpwd initial_pwd dir base
+ initial_oldpwd="$OLDPWD"
+ initial_pwd="$PWD"
+ if [[ $1 == */* ]]; then
+ dir="${1%/*}"
+ base="/${1##*/}"
+ # CDPATH because having it set will cause cd to possibly print output
+ CDPATH= cd "$dir"
+ printf "%s%s\n" "$PWD" "$base"
+ CDPATH= cd "$initial_pwd"
+ OLDPWD="$initial_oldpwd"
+ else
+ printf "%s/%s\n" "$PWD" "$1"
+ fi
+}
+# full path of directory without resolving symlinks
+fpd() {
+ local initial_oldpwd initial_pwd dir
+ initial_oldpwd="$OLDPWD"
+ initial_pwd="$PWD"
+ dir="$1"
+ CDPATH= cd "$dir"
+ printf "%s%s\n" "$PWD" "$base"
+ cd "$initial_pwd"
+ OLDPWD="$initial_oldpwd"
}
fi
jobs_char=
if [[ $(jobs -p) ]]; then
- jobs_char='\j '
+ jobs_char='j\j '
fi
# We could test if sudo is active with sudo -nv
# but then we get an email and log of lots of failed sudo commands.
/a/opt/android-studio/bin/studio.sh "$@" & r
}
-# convert brains path to url
-# /f/brains/sysadmin/interns/2022/nick_shrader/intro_blog_post.mdwn
-# becomes
-# https://brains.fsf.org/wiki/sysadmin/interns/2022/nick_shrader/intro_blog_post
-iki() {
- local url path input
+# Convert brains file path to url and vice versa
+# usage: brains [URL_OR_PATH]
+brains() {
+ _iki-convert /f/brains brains.fsf.org "$@"
+}
+glue() {
+ _iki-convert /f/gluestick gluestick.office.fsf.org "$@"
+}
+
+# usage: $0 REPO_PATH [URL_OR_PATH]
+_iki-convert() {
+ local url path input err repo_dir domain filename dir path
+ local initial_oldpwd initial_pwd
+ repo_dir="$1"
+ domain="$2"
+ shift 2
+ err=false
+ if $err; then
+ return 1
+ fi
if [[ $1 ]]; then
input="$*"
else
- read -r -p "enter path or url" input
+ read -r -p "enter path or url"$'\n' input
fi
case $input in
http*)
- path="/f/brains/${input##https://brains.fsf.org/wiki/}"
+ path="$repo_dir/${input##https://$domain/wiki/}"
if [[ $path == */ ]]; then
path=${path%/}.mdwn
- fi
+ fi
j printf "%s\n" "$path"
;;
*)
- url=$(readlink -f "$input")
- url="https://brains.fsf.org/wiki/${url#*brains/}"
+ path=$(fp "$input")
+ url="https://$domain/wiki/${path#$repo_dir/}"
url="${url%.mdwn}/"
j echo "$url"
;;
esac
+}
+# Convert brains file path to url and vice versa. It copies the result to clipboard
+# usage: brains [URL_OR_PATH]
+brains() {
+ local url path input repo_dir err path
+ repo_dir=/a/f/brains
+ err=false
+ if ! type -p xclip &>/dev/null; then
+ echo "missing dependency for brains, please do: sudo apt install xclip" >&2
+ err=true
+ fi
+ if ! type -p pee &>/dev/null; then
+ echo "missing dependency for brains, please do: sudo apt install moreutils" >&2
+ err=true
+ fi
+ if $err; then
+ return 1
+ fi
+ if [[ $1 ]]; then
+ input="$*"
+ else
+ read -r -p "enter path or url"$'\n' input
+ fi
+ case $input in
+ http*)
+ path="$repo_dir/${input##https://brains.fsf.org/wiki/}"
+ if [[ $path == */ ]]; then
+ path=${path%/}.mdwn
+ fi
+ printf "%s\n" "$path" |& pee "xclip -r -selection clipboard" cat
+ ;;
+ *)
+ path=$(realpath -s "$input")
+ url="https://brains.fsf.org/wiki/${path#$repo_dir/}"
+ url="${url%.mdwn}/"
+ echo "$url" |& pee "xclip -r -selection clipboard" cat
+ ;;
+ esac
}
+
# Generate beet smartplaylists for navidrome.
# for going in the reverse direction, run
# /b/ds/navidrome-playlist-export
local escape_char escaped_input expected_input skip_input_regex right_pad erasable_line seek_sec
local pl_state_path pl_state_dir pl_state_file tmpstr
local new_random pl_seed_path seed_num seed_file fmt first_play
- local -a pl_tags buttons button_map ids tags tmp_tags initial_ls ls_lines paths
+ local -a buttons button_map ids tags tmp_tags initial_ls ls_lines paths
local -A button_i
local -i i j volume scrolled id_count line_int skip_start pre_j_count head_count skip_lookback
local -i overflow_lines overflow
fi
pl_state_dir=/i/info/pl-state
if [[ $playlist ]]; then
- pl_state_dir=$pl_state_dir/nopl
- else
pl_state_dir=$pl_state_dir/$playlist
+ else
+ pl_state_dir=$pl_state_dir/nopl
fi
pl_state_path=$pl_state_dir/$pl_state_file
pl_seed_path=$pl_state_dir/$seed_file
{ base64 < /dev/urandom | head -c 200 ||:; echo; } > $pl_seed_path
fi
-
-
# PijokVipiotOzeph is just a random string for a delimiter
fmt='%ifdef{rating,$rating }'"$fstring"'$genre | $title - $artist - $album $length $id PijokVipiotOzeph $path'
# shellcheck disable=SC2016 # obvious reason
rm $tmpf
}
+# prettify the date
+btrbk-date() {
+ local indate
+ indate="$1"
+ shift
+ date +%F_%T%:::z -d "$(sed -r 's/(.{4})(..)(.{5})(..)(.*)/\1-\2-\3:\4:\5/' <<<"$indate")" "$@"
+}
+btrbk-undate() {
+ # fudCaHougfirp is a random string
+ { if [[ $1 ]]; then
+ echo "$1"
+ else
+ cat
+ fi
+ } | sed -r 's/-0([45])( |$)/fudCaHougfirp0\100/;s/_/T/;s/[:-]//g;s/fudCaHougfirp/-/'
+
+}
+btrbk-date-sed() {
+ local line
+ while read -r line; do
+ if [[ $line == *20[0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]-0[45]00* ]]; then
+ pre="${line%%20[0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]-0[45]00*}"
+ post="${line##*20[0-9][0-9][0-9][0-9][0-9][0-9]T[0-9][0-9][0-9][0-9][0-9][0-9]-0[45]00}"
+ mid="${line:${#pre}:22}"
+ echo "$pre$(btrbk-date "$mid")$post"
+ else
+ echo "$line"
+ fi
+ done
+}
+jrbtrbk() {
+ jr -u btrbk-run -u btrbk -u switch-mail-host -u btrbk-spread "$@"
+}
+
+# internal function
+btrbk-host-debug-show-host() {
+ for f; do
+ snaphost=
+ for host in $remote $alt local; do
+ if line=$(grep -P "\S*$f" /tmp/b/s/$host.log); then
+ if [[ $snaphost ]]; then
+ e error: snaphost=$snaphost, host=$host line="$line"
+ fi
+ if [[ $line == ssh* ]]; then
+ tmp="${line#ssh://}"
+ snaphost="${tmp%%/*}"
+ else
+ snaphost=$host
+ fi
+ fi
+ done
+ echo $snaphost $f | btrbk-date-sed
+ done
+}
+
+# If we get a btrfs receive error like this:
+# ERROR: ... clone: did not find source subvol
+# running this command will help track down the problem.
+# Alter remote= and alt=. When I used it, remote is
+# the host having the error when I push a snapshot.
+# Alt is just the other host that takes snapshots
+# besides the local host.
+btrbk-host-debug() {
+
+ remote=b8.nz
+ alt=sywg.b8.nz
+
+ mkdir -p /tmp/b/s
+ for host in $remote $alt; do
+ # this takes a while, we only want to do it on 1st run
+ if [[ -s /tmp/b/$host.log ]]; then continue; fi
+ ssh $host journalctl -u btrbk-run -u btrbk -u switch-mail-host -u btrbk-spread >/tmp/b/$host.log
+ done
+ if [[ ! -s /tmp/b/local.log ]]; then
+ jrbtrbk >/tmp/b/local.log
+ fi
+ cd /tmp/b
+ for f in *.log; do
+ gr '\bsnapshot success' $f >s/$f
+ done
+ cd /mnt/root/btrbk
+ localq=(q.*)
+ declare -A localq_a
+ for f in "${localq[@]}"; do
+ localq_a[$f]=t
+ done
+
+ remoteq=()
+ for f in $(ssh $remote "cd /mnt/root/btrbk; echo q.*"); do
+ if [[ ! ${localq_a[$f]} ]]; then
+ remoteq+=($f)
+ fi
+ done
+ btrbk-host-debug-show-host "${localq[@]}"
+ if (( ${#remoteq[@]} >= 1 )); then
+ echo "=== $remote only ===="
+ btrbk-host-debug-show-host ${remoteq[@]}
+ fi
+
+}
+
# note, to check for glue records
# First, find some the .org nameservers:
# dig +trace iankelling.org
wg genkey | tee $name-priv.key | wg pubkey > $name-pub.key
umask $umask_orig
}
+
+
+# extrahost is a host/cidr that is allowed to go be routed through the vpn by this host.
+#
wghole() {
- if (( $# != 2 )); then
- e expected 2 arg of hostname, ip suffix >&2
+ if (( $# < 2 || $# > 3 )); then
+ e expected 2-3 arg of hostname, ip suffix, and extrahost >&2
return 1
fi
local host ipsuf umask_orig
host=$1
ipsuf=$2
+ if [[ $3 ]]; then
+ extrahost=,$3
+ fi
mkdir -p /p/c/machine_specific/$host/filesystem/etc/wireguard
(
cd /p/c/machine_specific/$host/filesystem/etc/wireguard
[Peer]
# li. called wgmail on that server
PublicKey = CTFsje45qLAU44AbX71Vo+xFJ6rt7Cu6+vdMGyWjBjU=
-AllowedIPs = 10.8.0.0/24
+AllowedIPs = 10.8.0.0/24$extrahost
Endpoint = 72.14.176.105:1194
PersistentKeepalive = 25
EOF
myirc() {
if [[ ! $1 ]]; then
- set -- fsf-office
+ set -- fsfsys
fi
local -a d
d=( /var/lib/znc/moddata/log/iank/{freenode,libera} )
(sleep "$(calc "$* * 60")" && mpv --no-config --volume 50 /a/bin/data/alarm.mp3) > /dev/null 2>&1 &
}
+## usage: to connect to my main transmission daemon from a different host, run this
+trans-remote-route() {
+ :
+}
trg() { transmission-remote-gtk & r; }
+# TODO: this wont work transmission.lan doesnt exist
trc() {
# example, set global upload limit to 100 kilobytes:
# trc -u 100
calvis() { # calendar visualize
install -m 600 /dev/null /tmp/calendar-bytes
- while read l; do
+ while read -r l; do
for char in $l; do
printf "\x$(printf "%x" $char)" >>/tmp/calendar-bytes
done