Merge branch 'config' of uplime/rowbot into master
This commit is contained in:
commit
41a4842920
1 changed files with 131 additions and 129 deletions
260
rowbot
260
rowbot
|
@ -1,7 +1,36 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
###
|
||||||
|
# switch toggler
|
||||||
|
###
|
||||||
|
|
||||||
shopt -s nullglob dotglob extglob
|
shopt -s nullglob dotglob extglob
|
||||||
|
|
||||||
|
###
|
||||||
|
# utilities
|
||||||
|
###
|
||||||
|
|
||||||
|
parent() {
|
||||||
|
(( BASHPID == $$ ))
|
||||||
|
}
|
||||||
|
|
||||||
|
has() {
|
||||||
|
hash "$1" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
local status=1
|
||||||
|
|
||||||
|
if (( $# > 1 )) && [[ $1 = -s ]]; then
|
||||||
|
status=$2
|
||||||
|
shift
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
error "$@"
|
||||||
|
exit "$status"
|
||||||
|
}
|
||||||
|
|
||||||
###
|
###
|
||||||
# logger
|
# logger
|
||||||
###
|
###
|
||||||
|
@ -13,7 +42,7 @@ declare -A levels=(
|
||||||
|
|
||||||
log() {
|
log() {
|
||||||
if [[ -v LEVEL ]] && (( levels[$level] <= levels[$LEVEL] )); then
|
if [[ -v LEVEL ]] && (( levels[$level] <= levels[$LEVEL] )); then
|
||||||
printf "%s: $1\n" "${LEVEL^^}" "${@:2}" >&"$log"
|
printf "%s: $1\n" "${LEVEL^^}" "${@:2}" >&"$log_fd"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +66,7 @@ error() {
|
||||||
# argument parser for parsing arguments
|
# argument parser for parsing arguments
|
||||||
##
|
##
|
||||||
|
|
||||||
original_args=("$0" "$@")
|
original_args=( "$@" )
|
||||||
declare -A opts
|
declare -A opts
|
||||||
|
|
||||||
while (( $# )); do
|
while (( $# )); do
|
||||||
|
@ -69,79 +98,118 @@ done
|
||||||
# default config
|
# default config
|
||||||
##
|
##
|
||||||
|
|
||||||
server=${opts[server]:-irc.libera.chat}
|
server=irc.libera.chat port=6667 tls=no client_cert=
|
||||||
tls=${opts[tls]:-no}
|
nick=rowbot-dev ident=rowbot realname=rowbot chan=
|
||||||
|
trigger=\` fact_root=. reload=no level=info log_fd=1 log=
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
sys_root=sysfacts owner=${USER:-uplime} dev=no
|
||||||
|
|
||||||
|
###
|
||||||
|
# apply custom config
|
||||||
|
###
|
||||||
|
|
||||||
|
for file do
|
||||||
|
if [[ -f $file ]]; then
|
||||||
|
# These files are provided dynamically at run-time.
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "$file" # ha, dot file
|
||||||
|
else
|
||||||
|
die 'could not locate config file %s' "$file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
###
|
||||||
|
# apply command line options
|
||||||
|
###
|
||||||
|
|
||||||
|
if [[ -v opts[tls] ]]; then
|
||||||
|
tls=${opts[tls]}
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $tls = yes ]]; then
|
if [[ $tls = yes ]]; then
|
||||||
if ! hash socat 2>/dev/null; then
|
# This is a false positive.
|
||||||
printf 'please install socat to use tls with rowbot.\n' >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# false positive
|
|
||||||
# shellcheck disable=SC2102
|
# shellcheck disable=SC2102
|
||||||
if [[ -v opts[client-cert] ]]; then
|
if ! has socat; then
|
||||||
|
die "please install socat to use tls with rowbot."
|
||||||
|
elif [[ -v opts[client-cert] ]]; then
|
||||||
client_cert=${opts[client-cert]}
|
client_cert=${opts[client-cert]}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
port=${opts[port]:-6697}
|
port=6697
|
||||||
else
|
|
||||||
port=${opts[port]:-6667}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nick=${opts[nick]:-rowbot-dev}
|
config=(
|
||||||
ident=${opts[ident]:-rowbot}
|
server port nick ident realname chan trigger
|
||||||
realname=${opts[realname]:-rowbot}
|
fact_root reload dev level log owner sys_root
|
||||||
chan=${opts[chan]:-}
|
reload
|
||||||
trigger=${opts[trigger]:-\`}
|
)
|
||||||
fact_root=${opts[fact-root]:-.}
|
|
||||||
reload=${opts[reload]:-no}
|
|
||||||
dev=${opts[dev]:-no}
|
|
||||||
sysfacts_file=${opts[sysfacts]:-./sysfacts.txt}
|
|
||||||
|
|
||||||
if [[ -v USER ]]; then
|
for opt in "${config[@]}"; do
|
||||||
owner=${opts[owner]:-"$USER"}
|
declare -n config_var=$opt
|
||||||
else
|
cmd_arg=${opt//_/-}
|
||||||
owner=${opts[owner]:-uplime}
|
|
||||||
fi
|
|
||||||
|
|
||||||
level=${opts[log-level]:-info}
|
if [[ -v opts[$cmd_arg] ]]; then
|
||||||
|
# This variable is only used for assignment.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
config_var=${opts[$cmd_arg]}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
if [[ $reload = yes ]]; then
|
if [[ $log && $reload = no ]]; then
|
||||||
log=$LOG_FD
|
exec {log_fd}>"$log"
|
||||||
elif [[ ${opts[log]} ]]; then
|
|
||||||
exec {log}>"${opts[log]}"
|
|
||||||
else
|
|
||||||
log=1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
###
|
###
|
||||||
# utilities
|
# apply reloaded values
|
||||||
|
###
|
||||||
|
|
||||||
|
if [[ $reload = yes ]]; then
|
||||||
|
reload_vars=(
|
||||||
|
nick ident host level log log_fd alarm_pid tls_pid in_sock
|
||||||
|
out_sock sock_dir sys_root fact_root dev trigger registered
|
||||||
|
keep_trying desired_nick
|
||||||
|
)
|
||||||
|
|
||||||
|
for var in "${reload_vars[@]}"; do
|
||||||
|
env_var=${var^^}
|
||||||
|
declare -n reload_var=$var
|
||||||
|
|
||||||
|
if [[ -v $env_var ]]; then
|
||||||
|
# This variable is only used for assignment.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
reload_var=${!env_var}
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
###
|
||||||
|
# process management
|
||||||
###
|
###
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
debug "cleaning up rowbot"
|
debug "reaping rowbot's children"
|
||||||
|
|
||||||
if [[ -v tls_pid ]]; then
|
if [[ -v alarm_pid ]]; then
|
||||||
kill "$tls_pid"
|
debug "killing alarm process (%d) from %d" "$alarm_pid" "$BASHPID"
|
||||||
rm -rf "$sock_dir"
|
kill "$alarm_pid"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -v ping_pid ]]; then
|
if [[ -v tls_pid ]]; then
|
||||||
debug "cleaning up alarm in %d" "$BASHPID"
|
debug "killing tls process (%d) from %d" "$tls_pid" "$BASHPID"
|
||||||
kill "$ping_pid"
|
kill "$tls_pid"
|
||||||
|
rm -rf "$sock_dir"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -v tls_pid || $tls = no ]]; then
|
if [[ -v tls_pid || $tls = no ]]; then
|
||||||
exec {in_sock}>&- {out_sock}>&-
|
exec {in_sock}>&- {out_sock}>&-
|
||||||
|
|
||||||
if (( log != 1 )); then
|
if (( log_fd != 1 )); then
|
||||||
exec {log}>&-
|
exec {log_fd}>&-
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if (( BASHPID == $$ )); then
|
if parent; then
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -156,37 +224,6 @@ alarm-handler() {
|
||||||
|
|
||||||
trap alarm-handler ALRM
|
trap alarm-handler ALRM
|
||||||
|
|
||||||
###
|
|
||||||
# reload code
|
|
||||||
###
|
|
||||||
|
|
||||||
if [[ $reload = yes ]]; then
|
|
||||||
in_sock=$IN_SOCK out_sock=$OUT_SOCK
|
|
||||||
trigger=$TRIGGER dev=$DEV level=$LOG_LEVEL
|
|
||||||
registered=$REGISTERED
|
|
||||||
|
|
||||||
debug "doing a reload. pid is %d" "$BASHPID"
|
|
||||||
|
|
||||||
if [[ -v KEEP_TRYING ]]; then
|
|
||||||
keep_trying=$KEEP_TRYING desired_nick=$DESIRED
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $tls = yes ]]; then
|
|
||||||
sock_dir=$SOCK_DIR
|
|
||||||
tls_pid=$TLS_PID
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -v PING_PID ]]; then
|
|
||||||
ping_pid=$PING_PID
|
|
||||||
fi
|
|
||||||
|
|
||||||
nick=$NICK ident=$IDENT
|
|
||||||
|
|
||||||
if [[ -v HOST ]]; then
|
|
||||||
host=$HOST
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# net code
|
# net code
|
||||||
###
|
###
|
||||||
|
@ -195,10 +232,9 @@ if [[ $reload = no && $tls = yes ]]; then
|
||||||
sock_dir=$(mktemp -d)
|
sock_dir=$(mktemp -d)
|
||||||
mkfifo "$sock_dir"/rb{in,out}
|
mkfifo "$sock_dir"/rb{in,out}
|
||||||
|
|
||||||
if [[ -v client_cert ]]; then
|
if [[ $client_cert ]]; then
|
||||||
if [[ ! -f $client_cert ]]; then
|
if [[ ! -f $client_cert ]]; then
|
||||||
error "client certificate not found: %s" "$client_cert"
|
die "client certificate not found: %s" "$client_cert"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
conn_args=OPENSSL:$server:$port,cert=$client_cert
|
conn_args=OPENSSL:$server:$port,cert=$client_cert
|
||||||
|
@ -208,8 +244,8 @@ if [[ $reload = no && $tls = yes ]]; then
|
||||||
|
|
||||||
socat "$conn_args" - <"$sock_dir"/rbin >"$sock_dir"/rbout &
|
socat "$conn_args" - <"$sock_dir"/rbin >"$sock_dir"/rbout &
|
||||||
tls_pid=$!
|
tls_pid=$!
|
||||||
debug "created tls connection (pid %d)" "$tls_pid"
|
|
||||||
exec {out_sock}>"$sock_dir"/rbin {in_sock}<"$sock_dir"/rbout
|
exec {out_sock}>"$sock_dir"/rbin {in_sock}<"$sock_dir"/rbout
|
||||||
|
debug "created tls connection (pid %d)" "$tls_pid"
|
||||||
elif [[ $reload = no ]]; then
|
elif [[ $reload = no ]]; then
|
||||||
exec {sock}<>/dev/tcp/"$server"/"$port"
|
exec {sock}<>/dev/tcp/"$server"/"$port"
|
||||||
in_sock=$sock out_sock=$sock
|
in_sock=$sock out_sock=$sock
|
||||||
|
@ -218,7 +254,7 @@ fi
|
||||||
|
|
||||||
send() {
|
send() {
|
||||||
local fmt
|
local fmt
|
||||||
# As this is a printf wrapper, the format string is provided as an argument
|
# As this is a printf wrapper, the format string is provided as an argument.
|
||||||
# shellcheck disable=SC2059
|
# shellcheck disable=SC2059
|
||||||
printf -v fmt "$1" "${@:2}"
|
printf -v fmt "$1" "${@:2}"
|
||||||
printf '%s\r\n' "$fmt" >&"$out_sock"
|
printf '%s\r\n' "$fmt" >&"$out_sock"
|
||||||
|
@ -306,7 +342,7 @@ on_001() {
|
||||||
done
|
done
|
||||||
} &
|
} &
|
||||||
|
|
||||||
ping_pid=$!
|
alarm_pid=$!
|
||||||
nick=${params[0]}
|
nick=${params[0]}
|
||||||
registered=yes
|
registered=yes
|
||||||
who "$nick" %%uht,42
|
who "$nick" %%uht,42
|
||||||
|
@ -330,11 +366,11 @@ on_005() {
|
||||||
local param key value
|
local param key value
|
||||||
|
|
||||||
for param in "${params[@]:1:${#params[@]}-2}"; do
|
for param in "${params[@]:1:${#params[@]}-2}"; do
|
||||||
# This is a valid assignment, not a comparison
|
# This is a valid assignment, not a comparison.
|
||||||
# shellcheck disable=SC1097
|
# shellcheck disable=SC1097
|
||||||
IFS== read -r key value <<< "$param"
|
IFS== read -r key value <<< "$param"
|
||||||
# While isupport is unused, it's still there in case later code wants to
|
# While isupport is unused, it's still there in case later code wants to
|
||||||
# use it
|
# use it.
|
||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
isupport[$key]=$value
|
isupport[$key]=$value
|
||||||
debug "isupport: %s = %s" "$key" "$value"
|
debug "isupport: %s = %s" "$key" "$value"
|
||||||
|
@ -647,29 +683,18 @@ hook_post_PRIVMSG_control_panel() {
|
||||||
privmsg "$to" "joined ${words[1]}"
|
privmsg "$to" "joined ${words[1]}"
|
||||||
;;
|
;;
|
||||||
reload)
|
reload)
|
||||||
export IN_SOCK=$in_sock OUT_SOCK=$out_sock LOG_FD=$log DEV=$dev
|
reload_vars=(
|
||||||
export RELOAD_TO=$to TRIGGER=$trigger LOG_LEVEL=$level
|
nick ident host level log log_fd alarm_pid tls_pid in_sock
|
||||||
export NICK=$nick IDENT=$ident REGISTERED=$registered
|
out_sock sock_dir sys_root fact_root dev trigger registered
|
||||||
|
keep_trying desired_nick to
|
||||||
|
)
|
||||||
|
|
||||||
if [[ $keep_trying = yes ]]; then
|
for env_var in "${reload_vars[@]}"; do
|
||||||
export KEEP_TRYING=yes DESIRED=$desired_nick
|
export "${env_var^^}"="${!env_var}"
|
||||||
fi
|
done
|
||||||
|
|
||||||
if [[ -v host ]]; then
|
|
||||||
export HOST=$host
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $tls = yes ]]; then
|
|
||||||
export SOCK_DIR=$sock_dir
|
|
||||||
export TLS_PID=$tls_pid
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -v ping_pid ]]; then
|
|
||||||
export PING_PID=$ping_pid
|
|
||||||
fi
|
|
||||||
|
|
||||||
privmsg "$to" "reloading..."
|
privmsg "$to" "reloading..."
|
||||||
exec "${original_args[@]}" --reload
|
exec "$0" --reload "${original_args[@]}"
|
||||||
;;
|
;;
|
||||||
level)
|
level)
|
||||||
level=${words[1]}
|
level=${words[1]}
|
||||||
|
@ -713,29 +738,6 @@ hook_post_PRIVMSG_control_panel() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
sysfacts=( )
|
|
||||||
|
|
||||||
if [[ -f $sysfacts_file ]]; then
|
|
||||||
mapfile -t sysfacts < "$sysfacts_file"
|
|
||||||
fi
|
|
||||||
|
|
||||||
hook_post_PRIVMSG_sysfacts() {
|
|
||||||
local to=${params[0]} idx
|
|
||||||
|
|
||||||
if [[ ${params[0]:0:1} != \# ]]; then
|
|
||||||
to=$from
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ${words[0]} = "$trigger"sysfact ]]; then
|
|
||||||
if (( ${#sysfacts[@]} == 0 )); then
|
|
||||||
privmsg "$to" "sysfacts are not loaded :("
|
|
||||||
else
|
|
||||||
(( idx = RANDOM % ${#sysfacts[@]} ))
|
|
||||||
privmsg "$to" "sysfact #$(( idx + 1 )): ${sysfacts[$idx]}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
hook_post_433_alternick() {
|
hook_post_433_alternick() {
|
||||||
if [[ -z $desired_nick && $registered = no ]]; then
|
if [[ -z $desired_nick && $registered = no ]]; then
|
||||||
desired_nick=${params[1]}
|
desired_nick=${params[1]}
|
||||||
|
@ -755,7 +757,7 @@ hook_post_NICK_alternick() {
|
||||||
###
|
###
|
||||||
|
|
||||||
if [[ $reload = yes ]]; then
|
if [[ $reload = yes ]]; then
|
||||||
privmsg "$RELOAD_TO" done.
|
privmsg "$TO" done.
|
||||||
else
|
else
|
||||||
registered=no
|
registered=no
|
||||||
info "rowbot's pid is %d" "$BASHPID"
|
info "rowbot's pid is %d" "$BASHPID"
|
||||||
|
|
Loading…
Reference in a new issue