Friday, June 10, 2011

A simple bash IRC logging bot

Couple of years ago I googled for a simple bash IRC logging bot that I could start on my router to log some channels. I've found a very simple script that worked but didn't handle PINGs from the server. So I extended it a bit trying to keep it as simple as possible.

root@alix:~# cat ./irclogbot.sh 
#!/bin/sh 

nick="blb$$"
channel=testchannel
server=irc.freenode.net
config=/tmp/irclog

[ -n "$1" ] && channel=$1
[ -n "$2" ] && server=$2
config="${config}_${channel}"

echo "NICK $nick" > $config 
echo "USER $nick +i * :$0" >> $config 
echo "JOIN #$channel" >> $config 

trap "rm -f $config;exit 0" INT TERM EXIT

tail -f $config | nc $server 6667 | while read MESSAGE 
do
  case "$MESSAGE" in
    PING*) echo "PONG${MESSAGE#PING}" >> $config;;
    *QUIT*) ;;
    *PART*) ;;
    *JOIN*) ;;
    *NICK*) ;;
    *PRIVMSG*) echo "${MESSAGE}" | sed -nr "s/^:([^!]+).*PRIVMSG[^:]+:(.*)/[$(date '+%R')] \1> \2/p";;
    *) echo "${MESSAGE}";;
  esac
done 


PING's are handled in the line 22. Lines 23-27 are only added to make output readable and could be removed to log raw data. 

The feedback inside of the 'while' loop allows me to use the script as a simple client too. IRC commands written into the $config file will be executed. For example one can send a text message into the channel by writing the following command:

echo "PRIVMSG #testchannel :Testing bash bot. Ignore it" >> /tmp/irclog_testchannel 
which makes it possible to re-purpose the bot by adding additional logic.

Insted of nc one can use telnet and in this case only busybox internal commands will be used

3 comments:

Erik said...

That`s just awesome. I was about to write my own bash script for logging but failed. Then I found yours and it`s exactly what I wanted to do. Best of all: I know what I did wrong now and understood how easy it really is :)

Thanks a lot

Erik

Anonymous said...

Thanks for sharing this. It was very useful to me.

I have changed a few things to avoid using nc, and use Bash built-in TCP sockets.

---

# Open the TCP connection.
exec 3<>/dev/tcp/$SERVER/$PORT
...
# Process each server command and logs everything.
while read -u 3 MESSAGE
do
MESSAGE=$(sed 's/\r//' <<< $MESSAGE )
echo "$(date -u +'%F %T') $MESSAGE" >>$LOG
case "$MESSAGE" in

alex said...

yes, you can use bash sockets too but as I mentioned already neither nc nor bash is available on an embedded system with the busybox and ash. Replacing nc with telnet makes the script working on my router too.