Implement the client to client protocol (CTCP)

This commit is contained in:
Nick Chambers 2021-06-15 19:07:32 -05:00
parent 4325450207
commit bda8167b02
1 changed files with 124 additions and 6 deletions

130
rowbot
View File

@ -1,5 +1,7 @@
#!/usr/bin/env bash
shopt -s nullglob dotglob extglob
###
# logger
###
@ -76,6 +78,10 @@ if [[ $tls = yes ]]; then
exit 1
fi
if [[ -v opts[client-cert] ]]; then
client_cert=${opts[client-cert]}
fi
port=${opts[port]:-6697}
else
port=${opts[port]:-6667}
@ -130,6 +136,7 @@ trap cleanup EXIT
###
if [[ $reload = yes ]]; then
debug "starting reload. pid is %d" "$$"
in_sock=$IN_SOCK out_sock=$OUT_SOCK
if [[ $tls = yes ]]; then
@ -143,12 +150,21 @@ if [[ $reload = yes ]]; then
elif [[ $tls = yes ]]; then
sock_dir=$(mktemp -d)
mkfifo "$sock_dir"/rb{in,out}
socat OPENSSL:"$server":"$port" - <"$sock_dir"/rbin >"$sock_dir"/rbout &
if [[ -v client_cert ]]; then
conn_args=OPENSSL:$server:$port,cert=$client_cert
else
conn_args=OPENSSL:$server:$port
fi
socat "$conn_args" - <"$sock_dir"/rbin >"$sock_dir"/rbout &
tls_pid=$!
debug "created tls connection (pid %d)" "$tls_pid"
exec {out_sock}>"$sock_dir"/rbin {in_sock}<"$sock_dir"/rbout
else
exec {sock}<>/dev/tcp/"$server"/"$port"
in_sock=$sock out_sock=$sock
debug "created plaintext connection"
fi
send() {
@ -181,15 +197,27 @@ on_JOIN() {
on_MODE() {
if (( ${#params[@]} == 2 )); then
info "%s sets mode(s) %s on %s" "$from" "${params[1]}" "${params[0]}"
else
warn "mode line was not handled: %s" "$orig_line"
elif (( ${#params[@]} > 2 )); then
info "%s: %s sets mode(s) %s" "${params[0]}" "$from" "${params[*]:1}"
fi
}
on_NICK() {
info "%s has changed their name to %s" "$from" "${params[0]}"
}
on_NOTICE() {
info "[%s/%s] %s" "$from" "${params[0]}" "${params[1]}"
}
on_PART() {
if (( ${#params[@]} > 1 )); then
info "%s has left %s: %s" "$from" "${params[0]}" "${params[1]}"
else
info "%s has left %s" "$from" "${params[0]}"
fi
}
on_PING() {
pong "${params[1]}"
debug "received ping: %s" "${params[0]}"
@ -322,7 +350,21 @@ join() {
nick() {
send "NICK %s" "$1"
info "changing nickname to %s" "$1"
}
notice() {
send "NOTICE %s :%s" "$1" "$2"
info "[%s/%s] %s" "$nick" "$1" "$2"
}
part() {
if (( $# )); then
if (( $# > 1 )); then
send "PART $1 :$2"
else
send "PART $1"
fi
fi
}
ping() {
@ -338,14 +380,68 @@ privmsg() {
info "<%s/%s> %s" "$nick" "$1" "$2"
}
quit() {
if (( $# )); then
send "QUIT :%s" "$1"
else
send QUIT
fi
}
user() {
send "USER %s * * :%s" "$ident" "$realname"
send "USER %s 0 * :%s" "$ident" "$realname"
}
###
# app hooks
##
hook_pre_PRIVMSG_CTCP() {
if [[ ${params[1]} != $'\x01'*$'\x01' ]]; then
return 0
fi
local cmd msg
cmd=${params[1]#$'\x01'} cmd=${cmd%% *}
msg=${params[1]#* } msg=${msg%$'\x01'}
if [[ ${cmd^^} = ACTION ]]; then
if [[ ${params[0]:0:1} = \# ]]; then
info "ctcp: %s: %s %s" "${params[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]}"
return 1
fi
info "ctcp: sending %s to %s" "${cmd^^}" "$from"
case ${cmd^^} in
CLIENTINFO)
notice "$from" $'\x01'"CLIENTINFO ACTION CLIENTINFO PING SOURCE TIME VERSION"$'\x01'
;;
PING)
local msg
msg=${params[1]#* } msg=${msg%$'\x01'}
notice "$from" $'\x01'"PING $msg"$'\x01'
;;
SOURCE)
notice "$from" $'\x01'"SOURCE https://ahti.space/git/uplime/rowbot"$'\x01'
;;
TIME)
notice "$from" $'\x01'"TIME time for you to get a watch"$'\x01'
;;
VERSION)
notice "$from" $'\x01'"VERSION rowbot v2"$'\x01'
esac
return 1
}
hook_post_PRIVMSG_factoids() {
if [[ ${params[0]:0:1} != \# ]]; then
return 0
@ -414,9 +510,11 @@ hook_post_PRIVMSG_control_panel() {
;;
join)
join "${words[1]}"
privmsg "$to" "joined ${words[1]}"
;;
reload)
export IN_SOCK=$in_sock OUT_SOCK=$out_sock LOG_FD=$log
export RELOAD_TO=$to
if [[ $tls = yes ]]; then
export SOCK_DIR=$sock_dir
@ -430,6 +528,24 @@ hook_post_PRIVMSG_control_panel() {
privmsg "$to" "reloading..."
exec "${original_args[@]}" --reload
;;
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"
else
dev=yes
privmsg "$to" "developer status enabled"
fi
;;
trigger)
if (( ${#words[@]} > 1 )); then
trigger=${words[1]}
privmsg "$to" "trigger is now $trigger"
fi
esac
fi
}
@ -438,7 +554,9 @@ hook_post_PRIVMSG_control_panel() {
# driver
###
if [[ $reload != yes ]]; then
if [[ $reload = yes ]]; then
privmsg "$RELOAD_TO" done.
else
nick "$nick"
user "$ident" "$realname"
fi