I just wrote an IRC bot in bash (I know, I know). It does everything I need it to (SASL auth, resolves links, etc.), except it doesn't connect over SSL. After much googling and much bothering on IRC, I have yet to find a way to get /dev/tcp to use SSL. Here is my current code:
#!/bin/bash
if [[ "$1" == "-debug" ]]; then
set -x
fi
irc_send() {
printf ">>> %s\n" "$1"
printf "%s\r\n" "$1" >&3 &
}
sasl_successful() {
while read -ru3 line; do
printf "%s\n" "$line"
read -r location numeric rest <<< "$line"
if [[ "$numeric" == "903" ]]; then
return 0
elif [[ "$numeric" == "904" || "$numeric" == "906" ]]; then
return 1
fi
done
}
sasl_connect() {
user="$1"
pass="$2"
server_pass="$3"
nick="$4"
ident="$5"
realname="$6"
saslstring="$(printf '%s\0%s\0%s' "$user" "$user" "$pass" | base64)"
irc_send "CAP REQ :sasl"
if [[ "$server_pass" ]]; then
irc_send "PASS $server_pass"
fi
irc_send "NICK $nick"
irc_send "USER $ident * * :$realname"
irc_send "AUTHENTICATE PLAIN"
irc_send "AUTHENTICATE $saslstring"
if sasl_successful; then
irc_send "CAP END"
return 0
else
return 1
fi
}
get_title() {
xmllint --html --xpath '//title/text()' - <<< "$(curl -sL "$1")" 2> /dev/null
}
domain_base() {
domain="$(python -c "import urlparse; print urlparse.urlparse('$1').netloc")"
if [[ -z "$domain" ]]; then
echo "$1"
else
echo "$domain"
fi
}
links=(
'http://static.giantbomb.com/uploads/square_small/2/25062/833357-link_avatar3.jpg'
'http://vignette1.wikia.nocookie.net/zelda/images/2/2a/Fierce_Deity_Link.png/revision/latest?cb=20100124002042'
'http://8wayrun.com/attachments/lnksc2art2-jpg.3846/'
'https://camo.githubusercontent.com/9bb56499161ec0a5c20b6b3a3af674f51072af7c/687474703a2f2f7777772e6e6f727468636173746c652e636f2e756b2f6775696c642f6172742f616e6e615f6c2f6c696e6b312e6a7067'
'http://www.jdubuzz.com/files/2015/05/Link_3_ST.png'
'http://www.smashbros.com/images/og/link.jpg'
'https://upload.wikimedia.org/wikipedia/en/3/39/Wakerlink.jpg'
)
host="irc.freenode.net"
server_pass=""
port=6667
nick="mewtwo"
user="mewtwo"
realname="A simple irc bot written in bash."
channels="#somechannel"
username="$1"
password="$2"
exec 3<>"/dev/tcp/$host/$port"
if ! sasl_connect "$username" "$password" "$server_pass" "$nick" "$user" "$realname"; then
printf "Could not connect.\n" >&2
fi
irc_send "JOIN $channels"
while :; do
irc_send "PING $RANDOM"
sleep 1m
done &
while read -ru3 line; do
line="$(perl -pe 's/\r\n/\n/' <<< "$line")"
read -r from type target msg <<< "$line"
msg="${msg#:}" nick="${from#:}" nick="${nick%%!*}" host="${from%%@*}" host="${from#"$host"@}"
# parsing logic
if [[ "$type" == "PRIVMSG" ]]; then
printf "[%s] %s@%s: %s\n" "$target" "$nick" "$host" "$msg" &
else
printf "%s\n" "$line" &
fi
# response logic
if [[ "$type" == "PRIVMSG" ]]; then
if [[ "$msg" == "link?" ]]; then
irc_send "PRIVMSG $target :${links[RANDOM % ${#links[@]}]}"
fi
urls=($(grep -oPm 1 '(?:https?:\/\/)?([a-z\d-]*\.)?[a-z\d-]+\.[a-z]+(?:\/\S*)?(?(?<=\.(jpg|png|gif))(*SKIP)(*F))' <<< "$msg"))
for url in "${urls[@]}"; do
irc_send "PRIVMSG $target :[$(get_title "$url")] - $(domain_base "$url")"
done
fi
done
Any suggestions are welcome!
Open SSL socket with OpenSSL and talk to it with stdin stdout
openssl s_client irc.freenode.net:7070
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With