Implement an IRC parser, and make net connections reloadable

This commit is contained in:
Nick Chambers 2021-07-06 03:27:07 -05:00 committed by Nick Chambers
parent 6164d713df
commit f7c146b556
1 changed files with 120 additions and 9 deletions

129
rowbot
View File

@ -162,6 +162,33 @@ on_sys_first_001_bootup() {
log_info "rowbot's pid is %d" "$$"
}
on_sys_first_999_bootup() {
log_debug "registering with the server"
nick "${config[nick]}"
user "${config[ident]}" "${config[realname]}"
}
on_sys_before_999_bootup() {
local setting setting_name
log_debug "storing the config"
for setting in "${!config[@]}"; do
setting_name=${setting//-/_}
export "CONFIG_${setting_name^^}=${config[$setting]}"
done
}
on_sys_after_001_bootup() {
log_debug "reloading the config"
local setting setting_name
while IFS= read -r setting; do
setting_name=${setting#CONFIG_} setting_name=${setting_name//_/-}
config[${setting_name,,}]=${!setting}
unset "$setting"
done < <(compgen -e CONFIG_)
}
on_sys_exit_999_bootup() {
log_info "Theres a lot of beauty in ordinary things. Isnt that kind of the point?"
}
@ -227,9 +254,16 @@ on_sys_init_001_log() {
fi
}
on_sys_before_999_log() {
if [[ -v log_fd ]] && (( log_fd != 1 )); then
log_debug "shutting logger down for reload"
exec {log_fd}>&-
fi
}
on_sys_exit_999_log() {
if [[ -v log_fd ]] && (( log_fd != 1 )); then
log_debug "shutting logger down"
log_debug "shutting logger down for good"
exec {log_fd}>&-
fi
}
@ -302,6 +336,25 @@ on_sys_first_002_net() {
fi
}
on_sys_before_002_net() {
if [[ ${config[tls]} = no ]]; then
export IRC_SOCK=$irc_sock
else
export SOCK_DIR=$sock_dir TLS_PID=$tls_pid
export OUT_SOCK=$out_sock IN_SOCK=$in_sock
fi
}
on_sys_after_002_net() {
if [[ ${config[tls]} = no ]]; then
irc_sock=$IRC_SOCK out_sock=$irc_sock in_sock=$irc_sock
unset IRC_SOCK
else
sock_dir=$SOCK_DIR tls_pid=$TLS_PID out_sock=$OUT_SOCK in_sock=$IN_SOCK
unset sock_dir tls_pid out_sock in_sock
fi
}
on_sys_exit_998_net() {
if [[ ${config[tls]} = no ]]; then
log_info "rowbot is closing the connection to irc://%s:%s" "${config[server]}" "${config[port]}"
@ -317,6 +370,18 @@ on_sys_exit_998_net() {
fi
}
###
# irc send handlers
###
nick() {
net_send "NICK :%s" "$1"
}
user() {
net_send "USER %s 0 * :%s" "$1" "$2"
}
###
# cleanup
###
@ -333,16 +398,9 @@ trap cleanup EXIT
###
reload_config() {
local setting setting_name
run_callbacks on_sys_before_
run_callbacks on_before_
for setting in "${!config[@]}"; do
setting_name=${setting//-/_}
export "${setting_name^^}"="${config[$setting]}"
done
exec "${cmd_line[@]}"
RELOADED=yes exec "${cmd_line[@]}"
}
reload_hup() {
@ -366,3 +424,56 @@ else
run_callbacks on_sys_first_
run_callbacks on_first_
fi
###
# driver/protocol parser
###
while net_recv line; do
declare -A msg=([words]=no [original]="$line")
# parse prefix in the style of nick!ident@host
if [[ ${line:0:1} = :* ]]; then
prefix=${line%% *} prefix=${prefix#:} line=${line#:"$prefix"} line=${line# }
log_debug "parsing message prefix %s" "$prefix"
msg[host]=${prefix#*@} prefix=${prefix%"${msg[host]}"} prefix=${prefix%@}
if [[ $prefix ]]; then
msg[ident]=${prefix#*!}
if [[ ${msg[ident]} != "$prefix" ]]; then
msg[nick]=${prefix%!*}
fi
fi
fi
# parse command formatted as a 3 digit integer or as a word consisting of
# alphabet values
msg[cmd]=${line%% *} line=${line#"${msg[cmd]}"} line=${line# }
log_debug "parsing message command %s" "${msg[cmd]}"
# parse the remaining values into white-space separated arguments
msg_args=()
while [[ $line ]]; do
if [[ ${line:0:1} = : ]]; then
msg_args+=( "${line:1}" ) msg[words]=yes line=
# Code using this array will be implemented later.
# shellcheck disable=SC2034
read -ra msg_words <<< "${msg_args[-1]}"
log_debug "parsed final argument %s" "${msg_args[-1]}"
else
arg=${line%% *} msg_args+=( "$arg" ) line=${line#"$arg"} line=${line# }
log_debug "parsed argument %s" "$arg"
fi
done
if has irc_on_"${msg[cmd]^^}"; then
irc_on_"${msg[cmd]^^}"
else
log_warn "unhandled line: %s" "${msg[original]}"
fi
done