Add a logging interface
This commit is contained in:
parent
d2965c9233
commit
dece4203b4
306
rowbot
306
rowbot
|
@ -6,111 +6,6 @@
|
|||
|
||||
shopt -s dotglob extglob lastpipe nullglob
|
||||
|
||||
###
|
||||
# configure rowbot
|
||||
###
|
||||
|
||||
# default config
|
||||
|
||||
declare -A config=(
|
||||
# connection settings
|
||||
[server]=irc.libera.chat [port]="" [tls]=no [client-cert]=""
|
||||
# irc registration settings
|
||||
[nick]=rowbot-dev [ident]=rowbot [realname]=rowbot [chan]=""
|
||||
# bot control settings
|
||||
[owner]="${USER:-uplime}" [trigger]=\` [dev]=yes
|
||||
# log settings
|
||||
[log]="" [overwrite]=no [log-level]=info
|
||||
)
|
||||
|
||||
# parse command line arguments
|
||||
|
||||
declare -A opts
|
||||
# This code is not used yet, but will be later.
|
||||
# shellcheck disable=SC2034
|
||||
cmd_line=( "${@:0}" )
|
||||
|
||||
while (( $# )); do
|
||||
case $1 in
|
||||
--*=*)
|
||||
key=${1#--} key=${key%%=*}
|
||||
opts[$key]=${1#--*=}
|
||||
;;
|
||||
--no-*)
|
||||
key=${1#--no-}
|
||||
opts[$key]=no
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
--*)
|
||||
key=${1#--}
|
||||
opts[$key]=yes
|
||||
;;
|
||||
*)
|
||||
break
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# apply custom configuration files
|
||||
|
||||
for file do
|
||||
if [[ -f $file ]]; then
|
||||
# These files (if any) are provided dynamically at run-time.
|
||||
# shellcheck disable=SC1090
|
||||
. "$file" # ha, dot file
|
||||
else
|
||||
die "could not locate config file %s" "$file"
|
||||
fi
|
||||
done
|
||||
|
||||
for setting in "${!config[@]}"; do
|
||||
if [[ -v ${setting//-/_} ]]; then
|
||||
declare -n setting_var=${setting//-/_}
|
||||
config[$setting]=$setting_var
|
||||
fi
|
||||
done
|
||||
|
||||
# apply command line arguments
|
||||
|
||||
for setting in "${!config[@]}"; do
|
||||
# This is a false positive.
|
||||
# shellcheck disable=SC2102
|
||||
if [[ -v opts[$setting] ]]; then
|
||||
config[$setting]=${opts[$setting]}
|
||||
fi
|
||||
done
|
||||
|
||||
# apply default port if one isn't provided
|
||||
|
||||
if [[ -z ${config[port]} ]]; then
|
||||
if [[ ${config[tls]} = yes ]]; then
|
||||
config[port]=6697
|
||||
else
|
||||
config[port]=6667
|
||||
fi
|
||||
fi
|
||||
|
||||
# apply any reloaded values
|
||||
|
||||
for setting in "${!config[@]}"; do
|
||||
env_name=${setting//-/_} env_name=${env_name^^}
|
||||
declare -n env_var=$env_name
|
||||
|
||||
if [[ -v $env_name ]]; then
|
||||
# This variable is only used for assignment.
|
||||
# shellcheck disable=SC2034
|
||||
config[$setting]=$env_var
|
||||
fi
|
||||
done
|
||||
|
||||
# cleanup
|
||||
|
||||
unset key file setting setting_var env_name env_var
|
||||
|
||||
###
|
||||
# utility and helper functions
|
||||
###
|
||||
|
@ -126,7 +21,12 @@ any_file() {
|
|||
}
|
||||
|
||||
die() {
|
||||
# error "$@"
|
||||
local fmt=$1
|
||||
shift
|
||||
# This is a wrapper around printf so the format string isn't known ahead of
|
||||
# time.
|
||||
# shellcheck disable=SC2059
|
||||
printf "$fmt\n" "$@" >&2
|
||||
exit "${STATUS:-42}"
|
||||
}
|
||||
|
||||
|
@ -135,15 +35,17 @@ get_option() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
local option_name=${1//-/_}
|
||||
declare -n option_var=$option_name
|
||||
local var_name=${1//-/_}
|
||||
local env_var=${var_name^^}
|
||||
|
||||
if [[ -v opts[$1] ]]; then
|
||||
option_var=${opts[log-level]}
|
||||
elif [[ ! -v $option_name ]]; then
|
||||
# This variable is only used for assignment.
|
||||
# shellcheck disable=SC2034
|
||||
option_var=$2
|
||||
if [[ -v $env_var ]]; then
|
||||
config[$1]=${!env_var}
|
||||
elif [[ -v opts[$1] ]]; then
|
||||
config[$1]=${opts[$1]}
|
||||
elif [[ -v $var_name ]]; then
|
||||
config[$1]=${!var_name}
|
||||
else
|
||||
config[$1]=$2
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -183,25 +85,187 @@ run_callbacks() {
|
|||
return 0
|
||||
}
|
||||
|
||||
###
|
||||
# configure rowbot's environment
|
||||
###
|
||||
|
||||
# parse command line arguments
|
||||
|
||||
declare -A opts
|
||||
cmd_line=( "${@:0}" )
|
||||
|
||||
while (( $# )); do
|
||||
case $1 in
|
||||
--*=*)
|
||||
key=${1#--} key=${key%%=*}
|
||||
opts[$key]=${1#--*=}
|
||||
;;
|
||||
--no-*)
|
||||
key=${1#--no-}
|
||||
opts[$key]=no
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
--*)
|
||||
key=${1#--}
|
||||
opts[$key]=yes
|
||||
;;
|
||||
*)
|
||||
break
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
# load custom configuration files
|
||||
|
||||
for file do
|
||||
if [[ -f $file ]]; then
|
||||
# These files (if any) are provided dynamically at run-time.
|
||||
# shellcheck disable=SC1090
|
||||
. "$file" # ha, dot file
|
||||
else
|
||||
die "could not locate config file %s" "$file"
|
||||
fi
|
||||
done
|
||||
|
||||
# cleanup
|
||||
|
||||
unset key file
|
||||
|
||||
###
|
||||
# load default config
|
||||
###
|
||||
|
||||
declare -A config
|
||||
|
||||
# connection settings
|
||||
|
||||
get_option server irc.libera.chat
|
||||
get_option tls no
|
||||
|
||||
if [[ ${config[tls]} = no ]]; then
|
||||
get_option port 6667
|
||||
else
|
||||
get_option client-cert ""
|
||||
get_option port 6697
|
||||
fi
|
||||
|
||||
# irc registration settings
|
||||
|
||||
get_option nick rowbot-dev
|
||||
get_option ident rowbot
|
||||
get_option realname rowbot
|
||||
get_option chan ""
|
||||
|
||||
# bot control settings
|
||||
|
||||
get_option owner "${USER:-uplime}"
|
||||
get_option trigger \`
|
||||
get_option dev yes
|
||||
|
||||
###
|
||||
# logger
|
||||
###
|
||||
|
||||
log() {
|
||||
if [[ -v LOG_LEVEL ]] && (( log_levels[$log_level] <= log_levels[$LOG_LEVEL] )); then
|
||||
printf "%s: $1\n" "${LOG_LEVEL^^}" "${@:2}" >&"$log_fd"
|
||||
fi
|
||||
}
|
||||
|
||||
log_debug() {
|
||||
LOG_LEVEL=debug log "$@"
|
||||
}
|
||||
|
||||
log_info() {
|
||||
LOG_LEVEL=info log "$@"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
LOG_LEVEL=warn log "$@"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
LOG_LEVEL=error log "$@"
|
||||
}
|
||||
|
||||
log_has_level() {
|
||||
local level
|
||||
|
||||
for level in "${!log_levels[@]}"; do
|
||||
if [[ ${1,,} = "$level" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
on_init_001_log() {
|
||||
declare -gA log_levels=( [debug]=1 [info]=2 [warn]=3 [error]=4 )
|
||||
get_option log-level info
|
||||
|
||||
if ! log_has_level "${config[log-level]}"; then
|
||||
die "%s is not a valid logging level" "${config[log-level]}"
|
||||
fi
|
||||
|
||||
get_option log ""
|
||||
get_option overwrite no
|
||||
log_level=${config[log-level]}
|
||||
|
||||
if [[ ${config[log]} ]]; then
|
||||
if [[ ${config[overwrite]} = yes ]]; then
|
||||
exec {log_fd}>"${config[log]}"
|
||||
else
|
||||
exec {log_fd}>>"${config[log]}"
|
||||
fi
|
||||
else
|
||||
log_fd=1
|
||||
fi
|
||||
}
|
||||
|
||||
on_exit_log() {
|
||||
if [[ -v log_fd ]] && (( log_fd != 1 )); then
|
||||
exec {log_fd}>&-
|
||||
fi
|
||||
}
|
||||
|
||||
###
|
||||
# cleanup
|
||||
###
|
||||
|
||||
cleanup() {
|
||||
run_callbacks on_exit_
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
###
|
||||
# live code reloader
|
||||
###
|
||||
|
||||
reload() {
|
||||
run_callbacks on_before_reload_
|
||||
local setting setting_name
|
||||
run_callbacks on_before_
|
||||
|
||||
for setting in "${!config[@]}"; do
|
||||
setting_name=${setting//-/_}
|
||||
export "${setting_name^^}"="${config[$setting]}"
|
||||
done
|
||||
|
||||
exec "${cmd_line[@]}"
|
||||
}
|
||||
|
||||
hup_reload() {
|
||||
log_info "received reload signal (HUP)"
|
||||
reload
|
||||
}
|
||||
|
||||
trap hup_reload HUP
|
||||
|
||||
on_init_debug() {
|
||||
declare -p config
|
||||
}
|
||||
|
||||
###
|
||||
# initialization sequence
|
||||
###
|
||||
|
@ -209,7 +273,9 @@ on_init_debug() {
|
|||
run_callbacks on_init_
|
||||
|
||||
if is_reloaded; then
|
||||
run_callbacks on_after_reload_
|
||||
run_callbacks on_after_
|
||||
else
|
||||
run_callbacks on_first_
|
||||
fi
|
||||
|
||||
declare -p config
|
||||
|
|
Loading…
Reference in New Issue