diff --git a/rowbot b/rowbot index 050e1d9..b67fba0 100755 --- a/rowbot +++ b/rowbot @@ -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 "There’s a lot of beauty in ordinary things. Isn’t 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