| #!/bin/bash
|
| shopt -s extglob
|
|
|
| if (($# < 2)) || [[ "$1" == @(--help|-h) ]]; then
|
| printf 'Usage: %q IRC-URI NICK [REALNAME [MESSAGES...]]\n' "$0" >&2
|
| printf 'IRC-URI: ircs://irc.example.org, irc://irc.example.net:6789\n' >&2
|
| printf 'REALNAME defaults to the value of NICK if omitted or empty\n' >&2
|
| printf 'MESSAGES are sent after successful connection registration\n' >&2
|
| exit 1
|
| fi
|
|
|
| uri="$1"
|
| nick="$2"
|
| real="${3:-"${nick}"}"
|
| shift 3
|
|
|
| if [[ "${uri}" != irc?(s)://+([^/:])?(:+([0-9])) ]]; then
|
| printf 'Invalid URI: %q\n' "${uri}" >&2
|
| exit 1
|
| fi
|
|
|
| proto=http
|
| if [[ "${uri}" == ircs://* ]]; then
|
| proto=https
|
| fi
|
| host="${uri#*//}"
|
|
|
| coproc curlfd {
|
| IFS= read -r # connect command after setting up the FD
|
| echo connecting >&2
|
| curl --request "USER ${nick} 0 * :${real}"$'\r\n'"NICK ${nick}"$'\r\nPING :' --upload-file - -H Host: -H User-Agent: -H Accept: -H Transfer-Encoding: -H Expect: --http0.9 --silent --verbose --no-buffer "${proto}://${host}"
|
| }
|
| exec 3>&"${curlfd[0]}"
|
| printf 'connect\n' >&"${curlfd[1]}"
|
|
|
| while :; do
|
| # Due to https://github.com/curl/curl/issues/16788 (and disabling Expect to avoid sending the header), curl won't return received lines until we send something. So send an empty line.
|
| printf '\r\n' >&"${curlfd[1]}"
|
| sleep 0.1
|
|
|
| # `read -t 0` returns success at EOF because it uses a `select` internally, i.e. tests whether `read` would block, not whether data is available, contrary to documentation.
|
| # https://lists.gnu.org/archive/html/bug-bash/2013-10/msg00029.html
|
| # https://lists.gnu.org/archive/html/bug-bash/2019-12/msg00082.html
|
| while read -t 0 -u 3 && IFS= read -r -u 3; do
|
| printf '%(%Y%m%dT%H%M%S)T < %s\n' -1 "${REPLY}"
|
| if [[ "${REPLY}" == ?(:+([^ ]) )PING' '?* ]]; then
|
| msg="${REPLY#?(+([^ ]) )PING }"
|
| printf '%(%Y%m%dT%H%M%S)T > PONG %s\n' -1 "${msg}"
|
| printf 'PONG %s\r\n' "${msg}" >&"${curlfd[1]}"
|
| elif (($#)) && [[ "${REPLY}" == ?(:+([^ ]) )001' '?* ]]; then
|
| for msg; do
|
| printf '%(%Y%m%dT%H%M%S)T > %s\n' -1 "${msg}"
|
| printf '%s\r\n' "${msg}" >&"${curlfd[1]}"
|
| shift
|
| sleep 0.5
|
| done
|
| fi
|
| done
|
|
|
| if [[ ! -n "${curlfd[0]}" ]]; then
|
| echo curl exited
|
| break
|
| fi
|
|
|
| while read -t 0 -u 0 && IFS= read -r -u 0; do
|
| printf '%(%Y%m%dT%H%M%S)T > %s\n' -1 "${REPLY}"
|
| printf '%s\r\n' "${REPLY}" >&"${curlfd[1]}"
|
| done
|
|
|
| sleep 0.5
|
| done
|