diff --git a/rowbot b/rowbot index fe5c975..7d28be7 100755 --- a/rowbot +++ b/rowbot @@ -273,61 +273,61 @@ recv() { ### on_ERROR() { - error "${params[0]}" + error "${args[0]}" exit } on_JOIN() { - info "%s has joined %s" "$from" "${params[0]}" + info "%s has joined %s" "$from" "${args[0]}" } on_MODE() { - if (( ${#params[@]} == 2 )); then - info "%s sets mode(s) %s on %s" "$from" "${params[1]}" "${params[0]}" - elif (( ${#params[@]} > 2 )); then - info "%s: %s sets mode(s) %s" "${params[0]}" "$from" "${params[*]:1}" + if (( ${#args[@]} == 2 )); then + info "%s sets mode(s) %s on %s" "$from" "${args[1]}" "${args[0]}" + elif (( ${#args[@]} > 2 )); then + info "%s: %s sets mode(s) %s" "${args[0]}" "$from" "${args[*]:1}" fi } on_NICK() { if [[ $from = "$nick" ]]; then - nick=${params[0]} + nick=${args[0]} fi - info "%s has changed their name to %s" "$from" "${params[0]}" + info "%s has changed their name to %s" "$from" "${args[0]}" } on_NOTICE() { - info "[%s/%s] %s" "$from" "${params[0]}" "${params[1]}" + info "[%s/%s] %s" "$from" "${args[0]}" "${args[1]}" } on_PART() { - if (( ${#params[@]} > 1 )); then - info "%s has left %s: %s" "$from" "${params[0]}" "${params[1]}" + if (( ${#args[@]} > 1 )); then + info "%s has left %s: %s" "$from" "${args[0]}" "${args[1]}" else - info "%s has left %s" "$from" "${params[0]}" + info "%s has left %s" "$from" "${args[0]}" fi } on_PING() { - pong "${params[1]}" - debug "received ping: %s" "${params[0]}" + pong "${args[1]}" + debug "received ping: %s" "${args[0]}" } on_PONG() { - debug "received pong: %s" "${params[1]}" + debug "received pong: %s" "${args[1]}" } on_PRIVMSG() { - info "<%s/%s> %s" "$from" "${params[0]}" "${params[1]}" + info "<%s/%s> %s" "$from" "${args[0]}" "${args[1]}" } on_QUIT() { - info "%s has disconnected: %s" "$from" "${params[0]}" + info "%s has disconnected: %s" "$from" "${args[0]}" } on_001() { - info %s "${params[1]}" + info %s "${args[1]}" if [[ $chan ]]; then join "$chan" @@ -343,21 +343,21 @@ on_001() { } & alarm_pid=$! - nick=${params[0]} + nick=${args[0]} registered=yes who "$nick" %%uht,42 } on_002() { - info %s "${params[1]}" + info %s "${args[1]}" } on_003() { - info %s "${params[1]}" + info %s "${args[1]}" } on_004() { - debug "%s " "${params[@]:1}" + debug "%s " "${args[@]:1}" } declare -A isupport @@ -365,7 +365,7 @@ declare -A isupport on_005() { local param key value - for param in "${params[@]:1:${#params[@]}-2}"; do + for param in "${args[@]:1:${#args[@]}-2}"; do # This is a valid assignment, not a comparison. # shellcheck disable=SC1097 IFS== read -r key value <<< "$param" @@ -378,81 +378,81 @@ on_005() { } on_250() { - info %s "${params[1]}" + info %s "${args[1]}" } on_251() { - info %s "${params[1]}" + info %s "${args[1]}" } on_252() { - info "There are %d operators online" "${params[1]}" + info "There are %d operators online" "${args[1]}" } on_253() { - info "There are %d unknown connections" "${params[1]}" + info "There are %d unknown connections" "${args[1]}" } on_254() { - info "There are %d channels formed" "${params[1]}" + info "There are %d channels formed" "${args[1]}" } on_255() { - info %s "${params[1]}" + info %s "${args[1]}" } on_265() { - info %s "${params[3]}" + info %s "${args[3]}" } on_266() { - info %s "${params[3]}" + info %s "${args[3]}" } on_315() { - debug "end of WHO for %s" "${params[1]}" + debug "end of WHO for %s" "${args[1]}" } on_332() { - info "topic for %s is %s" "${params[1]}" "${params[2]}" + info "topic for %s is %s" "${args[1]}" "${args[2]}" } on_333() { local date - printf -v date '%(%c)T' "${params[3]}" - info "topic for %s set by %s at %s" "${params[1]}" "${params[2]}" "$date" + printf -v date '%(%c)T' "${args[3]}" + info "topic for %s set by %s at %s" "${args[1]}" "${args[2]}" "$date" } on_353() { - info "members of %s: %s" "${params[2]}" "${params[3]}" + info "members of %s: %s" "${args[2]}" "${args[3]}" } on_354() { - if (( params[1] == 42 )); then + if (( args[1] == 42 )); then debug "received the identifying who" - ident=${params[2]} host=${params[3]} + ident=${args[2]} host=${args[3]} debug "ident=%s host=%s" "$ident" "$host" fi } on_366() { - debug "%s: end of NAMES list" "${params[1]}" + debug "%s: end of NAMES list" "${args[1]}" } on_372() { - info %s "${params[1]}" + info %s "${args[1]}" } on_375() { - debug %s "${params[1]}" + debug %s "${args[1]}" } on_376() { - debug %s "${params[1]}" + debug %s "${args[1]}" } on_433() { - info "somebody is already using %s" "${params[1]}" + info "somebody is already using %s" "${args[1]}" if [[ $registered = no ]]; then nick "${nick}_" @@ -460,7 +460,7 @@ on_433() { } on_473() { - error "%s: %s" "${params[1]}" "${params[2]}" + error "%s: %s" "${args[1]}" "${args[2]}" } ### @@ -552,24 +552,24 @@ who() { ## hook_pre_PRIVMSG_CTCP() { - if [[ ${params[1]} != $'\x01'*$'\x01' ]]; then + if [[ ${args[1]} != $'\x01'*$'\x01' ]]; then return 0 fi local cmd msg - cmd=${params[1]#$'\x01'} cmd=${cmd%% *} - msg=${params[1]#* } msg=${msg%$'\x01'} + cmd=${args[1]#$'\x01'} cmd=${cmd%% *} + msg=${args[1]#* } msg=${msg%$'\x01'} if [[ ${cmd^^} = ACTION ]]; then - if [[ ${params[0]:0:1} = \# ]]; then - info "ctcp: %s: %s %s" "${params[0]}" "$from" "$msg" + if [[ ${args[0]:0:1} = \# ]]; then + info "ctcp: %s: %s %s" "${args[0]}" "$from" "$msg" else info "privately, %s %s" "$from" "$msg" fi return 1 - elif [[ ${params[0]:0:1} = \# ]]; then - info "ctcp: %s has requested %s in %s" "$from" "${cmd^^}" "${params[0]}" + elif [[ ${args[0]:0:1} = \# ]]; then + info "ctcp: %s has requested %s in %s" "$from" "${cmd^^}" "${args[0]}" return 1 fi @@ -581,7 +581,7 @@ hook_pre_PRIVMSG_CTCP() { ;; PING) local msg - msg=${params[1]#* } msg=${msg%$'\x01'} + msg=${args[1]#* } msg=${msg%$'\x01'} notice "$from" $'\x01'"PING $msg"$'\x01' ;; SOURCE) @@ -597,156 +597,128 @@ hook_pre_PRIVMSG_CTCP() { return 1 } -hook_post_PRIVMSG_factoids() { - if [[ ${params[0]:0:1} != \# && $from != shikhin ]]; then - return 0 - elif [[ ${words[0]} = "$trigger"* ]]; then - local to=${params[0]} +hook_cmd_factoids() { + local key val facts msg - if [[ ${params[0]:0:1} != \# ]]; then - to=$from - fi + case $action in + is) + key=${action_line%% *} - case ${words[0]:${#trigger}} in - is) - if (( ${#words[@]} < 3 )); then - return 0 - fi - - local key val - key=${params[1]#*"$trigger"is} key=${key# } - val=${key#* } key=${key%% *} - - info "%s said in %s to remember %s as %s" "$from" "${params[0]}" "$key" "$val" - privmsg "$to" "I'm sure I'll remember that." - mkdir -p "$fact_root"/"${params[0]}" - printf %s "$val" > "$fact_root"/"${params[0]}"/"$key" - ;; - isnt) - if (( ${#words[@]} < 2 )); then - return 0 - fi - - local key - key=${params[1]#*"$trigger"isnt} key=${key# } - - if [[ -f $fact_root/${params[0]}/$key ]]; then - info "%s said in %s to delete %s" "$from" "${params[0]}" "$key" - privmsg "$to" "I forgot what that was anyways." - rm -f "$fact_root"/"${params[0]}"/"$key" - fi - ;; - ls) - local facts=( "$fact_root"/"${params[0]}"/* ) - privmsg "$to" "${facts[*]##*/}" - ;; - *) - local key=${words[0]:${#trigger}} - - if [[ -f $fact_root/${params[0]}/$key ]]; then - local msg - msg=$(<"$fact_root"/"${params[0]}"/"$key") - - if (( ${#words[@]} > 1 )) && [[ ${words[1]} = \> ]]; then - local target - target=${params[1]#*\>} target=${target# } target=${target% } - privmsg "$to" "$target: $msg" - else - privmsg "$to" "$from: $msg" - fi - fi - esac - fi -} - -hook_post_PRIVMSG_control_panel() { - if [[ ${words[0]} = "$trigger"* ]]; then - if [[ $from != "$owner" && $dev != yes ]]; then + if [[ $key = "$action_line" ]]; then + privmsg "$to" "$from: no fact provided" return 0 fi - local to=${params[0]} - - if [[ ${params[0]:0:1} != \# ]]; then - to=$from + val=${action_line#"$key" } + privmsg "$to" "I'm sure I'll remember that." + mkdir -p "$fact_root"/"$to" + printf %s "$val" > "$fact_root"/"$to"/"$key" + ;; + isnt) + if [[ -f $fact_root/$to/$action_line ]]; then + privmsg "$to" "I forgot what that was anyways." + rm -f "$fact_root"/"$to"/"$action_line" fi + ;; + ls) + facts=( "$fact_root"/"$to"/* ) + privmsg "$to" "${facts[*]##*/}" + ;; + *) + if [[ -f $fact_root/$to/$action ]]; then + msg=$(<"$fact_root"/"$to"/"$action") - case ${words[0]:${#trigger}} in - raw) - local cmd - cmd=${params[1]#"$trigger"raw} cmd=${cmd# } - info "%s is executing command: %s" "$from" "$cmd" - send "$cmd" - ;; - join) - join "${words[1]}" - privmsg "$to" "joined ${words[1]}" - ;; - reload) - 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 to - ) - - for env_var in "${reload_vars[@]}"; do - export "${env_var^^}"="${!env_var}" - done - - privmsg "$to" "reloading..." - exec "$0" --reload "${original_args[@]}" - ;; - level) - level=${words[1]} - privmsg "$to" "log level is now set to $level" - ;; - dev) - if [[ $dev = yes ]]; then - dev=no - privmsg "$to" "developer status disabled" + if [[ ${action_args[0]} = \> ]] && (( ${#action_args[@]} > 1 )); then + # Since it is assigning the last index of the array, it will always be a + # single string. + # shellcheck disable=SC2145 + privmsg "$to" "${action_args[@]:(-1)}: $msg" else - dev=yes - privmsg "$to" "developer status enabled" + privmsg "$to" "$from: $msg" fi - ;; - dev\?) - if [[ $dev = yes ]]; then - privmsg "$to" "developer status is enabled" - else - privmsg "$to" "developer status is disabled" - fi - ;; - trigger) - if (( ${#words[@]} > 1 )); then - trigger=${words[1]} - privmsg "$to" "trigger is now $trigger" - fi - ;; - msg) - if (( ${words[@]} > 2 )); then - privmsg "${words[1]}" "${words[*]:2}" - privmsg "$to" "sent message to ${words[1]}" - fi - ;; - cycle) - if [[ ${to:0:1} = \# ]]; then - privmsg "$to" "cycling channel $to" - part "$to" "be back soon!" - join "$to" - fi - esac + fi + esac +} + +hook_cmd_control_panel() { + if [[ $from != "$owner" && $dev != yes ]]; then + return 0 fi + + local channel env_var reload_vars recipient msg + + case $action in + raw) + info "%s is executing command: %s" "$from" "$action_line" + send "$action_line" + ;; + join) + for channel in "${action_args[@]}"; do + join "$channel" + privmsg "$to" "joined $channel" + done + ;; + reload) + 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 to + ) + + for env_var in "${reload_vars[@]}"; do + export "${env_var^^}"="${!env_var}" + done + + privmsg "$to" "reloading..." + exec "$0" --reload "${original_args[@]}" + ;; + level) + level=${action_args[0]} + privmsg "$to" "log level is now set to $level" + ;; + dev) + if [[ $dev = yes ]]; then + dev=no + privmsg "$to" "developer mode disabled" + else + dev=yes + privmsg "$to" "developer mode enabled" + fi + ;; + dev\?) + if [[ $dev = yes ]]; then + privmsg "$to" "developer mode is enabled" + else + privmsg "$to" "developer mode is disabled" + fi + ;; + trigger) + trigger=${action_args[0]} + privmsg "$to" "trigger is now '$trigger'" + ;; + cycle) + privmsg "$to" "cycling channel $to" + part "$to" "be right back!" + join "$to" + ;; + msg) + recipient=${action_line%% *} + msg=${action_line#"$recipient"* } + declare -p recipient msg action_line + privmsg "$recipient" "$msg" + privmsg "$to" "sent message to $recipient" + esac } hook_post_433_alternick() { if [[ -z $desired_nick && $registered = no ]]; then - desired_nick=${params[1]} + desired_nick=${args[1]} keep_trying=yes fi } hook_post_NICK_alternick() { - if [[ ${params[0]} = "$desired_nick" ]]; then + if [[ ${args[0]} = "$desired_nick" ]]; then keep_trying=no info "obtained nick %s" "$desired_nick" fi @@ -765,9 +737,23 @@ else user "$ident" "$realname" fi +# Always available: +# - from: name of the entity sending the message +# - ident: username of the entity sending the message +# - host: host of the entity sending the message +# - cmd: IRC command or numeric +# - args: array of arguments to the command + +# Available if `cmd` is set to "privmsg": +# - to: location to send the message back to + +# Additionally, if args[-1] starts with the trigger: +# - action: directive specified by the sender +# - action_line: data sent by the sender without the trigger or action +# - action_args: words sent by the sender without the trigger or action + while recv line; do - params=( ) - has_words=no + args=( ) orig_line=$line if [[ ${line:0:1} = : ]]; then @@ -783,20 +769,33 @@ while recv line; do while [[ $line ]]; do if [[ ${line:0:1} = : ]]; then - params+=("${line:1}") + args+=( "${line:1}" ) line="" - has_words=yes else - param=${line%% *} - params+=("$param") - line=${line#"$param"} line=${line# } + arg=${line%% *} + args+=( "$arg" ) + line=${line#"$arg"} line=${line# } fi done - if [[ $has_words = yes ]]; then - read -ra words <<< "${params[@]:(-1)}" - else - words=( ) + is_action=no + + if [[ ${cmd^^} = PRIVMSG ]]; then + # Since it is assigning the last index of the array, it will always be a + # single string. + # shellcheck disable=SC2124 + to=${args[0]} last=${args[@]:(-1)} + + if [[ ${to:0:1} != \# ]]; then + to=$from + fi + + if [[ $last = "$trigger"* ]]; then + is_action=yes + action=${last#"$trigger"} action=${action%% *} + action_line=${last#"$trigger$action" } + read -ra action_args <<< "$action_line" + fi fi skip_handler=0 @@ -806,17 +805,23 @@ while recv line; do (( skip_handler |= $? )) done < <(compgen -A function "hook_pre_${cmd^^}_") - if hash "on_${cmd^^}" 2>/dev/null; then + if has "on_${cmd^^}"; then if (( ! skip_handler )); then "on_${cmd^^}" else debug "handler for %s was skipped" "${cmd^^}" fi else - warn "unhandled line: %s" "$orig_line" + warn "unhandled line: %s" "$orig_line" fi while IFS= read -r hook; do "$hook" done < <(compgen -A function "hook_post_${cmd^^}_") + + if [[ $is_action = yes ]]; then + while IFS= read -r hook; do + "$hook" + done < <(compgen -A function "hook_cmd_") + fi done