216 lines
3.4 KiB
Bash
Executable File
216 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
###
|
|
# feature switch toggling
|
|
###
|
|
|
|
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
|
|
###
|
|
|
|
any_file() {
|
|
local files=( "${1:-.}"/* ) max idx
|
|
|
|
if (( ${#files[@]} > 1 )); then
|
|
(( max = ${#files[@]} - 1 ))
|
|
idx=$(random 0 "$max")
|
|
printf %s "${files[$idx]}"
|
|
fi
|
|
}
|
|
|
|
die() {
|
|
# error "$@"
|
|
exit "${STATUS:-42}"
|
|
}
|
|
|
|
get_option() {
|
|
if (( $# != 2 )); then
|
|
return 1
|
|
fi
|
|
|
|
local option_name=${1//-/_}
|
|
declare -n option_var=$option_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
|
|
fi
|
|
}
|
|
|
|
has() {
|
|
if (( $# )); then
|
|
hash "$1" 2>/dev/null
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
is_parent() {
|
|
(( BASHPID == $$ ))
|
|
}
|
|
|
|
is_reloaded() {
|
|
[[ $RELOADED = yes ]] || (( LORE_LIVES > 1 ))
|
|
}
|
|
|
|
random() {
|
|
local min=$1 max=$2
|
|
(( (RANDOM % max) + min ))
|
|
}
|
|
|
|
run_callbacks() {
|
|
if (( ! $# )); then
|
|
return 1
|
|
fi
|
|
|
|
local filter=$1
|
|
shift
|
|
|
|
while IFS= read -r; do
|
|
"$REPLY" "$@"
|
|
done < <(compgen -A function "$filter")
|
|
|
|
return 0
|
|
}
|
|
|
|
###
|
|
# live code reloader
|
|
###
|
|
|
|
reload() {
|
|
run_callbacks on_before_reload_
|
|
exec "${cmd_line[@]}"
|
|
}
|
|
|
|
hup_reload() {
|
|
reload
|
|
}
|
|
|
|
trap hup_reload HUP
|
|
|
|
on_init_debug() {
|
|
declare -p config
|
|
}
|
|
|
|
###
|
|
# initialization sequence
|
|
###
|
|
|
|
run_callbacks on_init_
|
|
|
|
if is_reloaded; then
|
|
run_callbacks on_after_reload_
|
|
else
|
|
run_callbacks on_first_
|
|
fi
|