Easier setup

This commit is contained in:
Neale Pickett 2012-05-14 14:37:28 -05:00
parent efb3c7063d
commit 95a18f7700
14 changed files with 112 additions and 242 deletions

99
README
View File

@ -1,5 +1,5 @@
bot
===
firebot
=======
This is a suite of simple programs which allow you to write an IRC bot.
It is based on the Unix principle that one program should do one thing,
@ -10,6 +10,46 @@ Unless you are a seasoned Unix programmer or are willing to become one,
this is not the bot you're looking for.
Getting Started Quickly
=======================
The `newmont` directory contains a very simple example, which you can
extend while it's running. It will connect to an IRC network, join
the channel `#dumont`, and respond to any channel massage containing
the substring "strawberry".
You should probably edit newmont/nickname and newmont/server before
trying this out. Set it to something hopefully unique on the network
you intend to join.
Start it like so:
./firebot newmont
What Everything Does
====================
The core fuctionality exists as two C programs and a couple scripts:
firebot
-------
Reads in nick and realname, sets up a fifo, connects to the server
(or runs `$botdir/connect`), and hands off to `connect-handler`.
connect-handler
---------------
Sends the `NICK` and `USER` commands to the server (or runs
`$botdir/login`), then hands off to `dispatch irc-filter
$botdir/handler`.
dispatch
--------
@ -20,8 +60,8 @@ limited. A fifo can optionally be specified on the command line;
anything written to it is treated identically to child output.
irc
---
irc-filter
----------
Parses its last argument as a line from IRC. Determines prefix,
command, sender, forum (channel or user), and text; then invokes a
@ -29,58 +69,9 @@ specified program with these as arguments. Also responds to server
pings as a convenience.
run
---
[run BOTDIR] will run the bot contained in $BOTDIR. It should contain
the following files (see cobalt in the distribution for examples):
* connect : program to open connection
* login : program to log in to IRC
* handler : program to handle IRC messages
firebot
-------
A private message handler providing a few handy commands.
infobot
-------
A private message handler providing infobot-like functionality.
notes
-----
A private message handler allowing users to leave notes for each other.
whuffie
-------
A private message handler keeping track of whuffe (also known as karma),
which is really just a meaningless number associated with your nick,
which other people can manipulate but you can't.
Putting it all together
=======================
A full chain of programs would look something like
tcpclient -> connect-handler -> dispatch -> handler
and would be invoked as
$ tcpclient irc.host.org 6667 ./connect-handler cobalt
Author
------
======
Neale Pickett <neale@woozle.org>

24
bot
View File

@ -1,24 +0,0 @@
#! /bin/sh -e
botdir=$1
d=$(dirname $0)
nickname=$(cat $botdir/nickname)
realname=$(cat $botdir/realname 2>/dev/null || \
echo "I'm a little printf, short and stdout.")
export nickname realname
(
# UCSPI wants input on FD 7, and sets $PROTO
[ -n "$PROTO" ] && exec 1>&7
if [ -x $botdir/login ]; then
$botdir/login
else
echo "NICK $nickname"
echo "USER $nickname $nickname $nickname :$realname"
fi
)
mkfifo -m 0600 $botdir/fifo
exec $d/dispatch -f $botdir/fifo $d/irc $botdir/handler

View File

@ -1,3 +0,0 @@
#! /bin/sh
exec socat OPENSSL:127.0.0.1:6697,verify=0,keepalive EXEC:"$*"

View File

@ -1,83 +0,0 @@
#! /bin/sh
prefix=$1; export prefix; shift
command=$1; export command; shift
sender=$1; export sender; shift
forum=$1; export forum; shift
text=$1; export text; shift
# $* is now args
# Debug output
#echo '>>>' ${prefix:+:}$prefix $command "$@" ${text:+:}"$text" 1>&2
raw () {
fmt="\007$1\n"; shift
printf "$fmt" "$@"
}
join () {
raw "JOIN $1"
}
cobalt () {
case "$1" in
air)
w3m -dump -cols 9999 'http://environweb.lanl.gov/Teom/teom30s.asp?MasterSiteID=211&offset=0' 2> /dev/null | \
awk '/.:..:.. .M/ {print "Los Alamos Air: " $5 "μg/m³ at " $2; exit}'
;;
nachos)
echo "aieeeee"
;;
*)
return 1
;;
esac
}
out=$(tempfile)
case $command in
001)
for i in $botdir/channels/*; do
join $(basename $i)
done
;;
433)
raw "NICK bot_$(shuf -c 1 /usr/share/dict/words)"
;;
PRIVMSG)
case "$forum" in
\#*)
cobalt "$text" || \
$ircdir/firebot "$text" || \
$ircdir/whuffie $botdir/whuffie.cdb "$text" || \
$ircdir/infobot $botdir/factoids.cdb "$text"
;;
esac
$ircdir/notes $botdir/notes "$text"
;;
INVITE)
join "$forum"
raw "PRIVMSG %s :Thanks for the invitation, %s." "$forum" "$sender"
touch $botdir/channels/$forum
;;
esac > $out
if [ "$forum" != "$sender" ] && [ $(wc -l < $out) -gt 5 ]; then
printf "PRIVMSG %s :Too many lines, sending privately.\r\n" "$forum"
forum=$sender
fi
while read -r line; do
case "$line" in
*)
printf "%s\r\n" "${line#}"
;;
*)
printf "PRIVMSG %s :%s\r\n" "$forum" "$line"
;;
esac
done < $out
rm -f $out

View File

@ -1,4 +0,0 @@
#! /bin/sh
echo "NICK cobalt"
echo "USER cobalt cobalt cobalt :I'm a little printf, short and stdout."

View File

@ -1,9 +1,5 @@
#! /bin/sh -e
botdir=$1
ircdir=$(dirname $0)
export botdir ircdir
# UCSPI wants communication on fd7
if [ -n "$PROTO" ]; then
fd=7
@ -11,10 +7,17 @@ else
fd=1
fi
$botdir/login 1>& $fd
if [ -p $botdir/fifo ]; then
fifo="-f $botdir/fifo"
if [ -x $botdir/login ]; then
$botdir/login 1>& $fd
else
echo "NICK $nickname" 1>& $fd
echo "USER $nickname $nickname $nickname :$realname" 1>& $fd
fi
exec $ircdir/dispatch $fifo $ircdir/irc-filter $botdir/handler
if [ -f $botdir/opts ]; then
read -r opts < $botdir/opts
else
opts="-i 500000"
fi
exec $ircdir/dispatch $fifo $opts $ircdir/irc-filter $botdir/handler

52
firebot
View File

@ -1,23 +1,35 @@
#! /bin/sh
#! /bin/sh -e
exec 2>&1
if ! [ -d $1 ]; then
echo "Usage: $0 BOTDIR"
echo
echo "Starts a new bot with personality defined in BOTDIR."
exit 1
fi
cmd=${1%% *}
[ "$cmd" = "$1" ] || args=${1#* }
case $cmd in
calc)
printf "%s = " "$args"
echo "$args" | bc -l
;;
units)
src=$(printf "%s" "$args" | sed 's/ ->.*//')
dst=$(printf "%s" "$args" | sed 's/.*-> //')
units -1 -v -- "$src" "$dst"
;;
*)
botdir=$(cd $1; pwd)
ircdir=$(cd $(dirname $0); pwd)
export botdir ircdir
nickname=$(cat $botdir/nickname)
realname=$(cat $botdir/realname 2>/dev/null || \
echo "I'm a little printf, short and stdout.")
export nickname realname
if [ -p $botdir/fifo ]; then
mkfifo -m 0600 $botdir/fifo
fifo="-f $botdir/fifo"
export fifo
fi
if [ -x $botdir/connect ]; then
$botdir/connect $ircdir/connect-handler
else
server=$(cat $botdir/server)
if [ -z "$server" ]; then
echo "$0: no server specified in $botdir/server"
exit 1
;;
esac
fi
socat TCP:$server EXEC:$ircdir/connect-handler
fi

23
modules/utilbot Executable file
View File

@ -0,0 +1,23 @@
#! /bin/sh
exec 2>&1
cmd=${1%% *}
[ "$cmd" = "$1" ] || args=${1#* }
case $cmd in
calc)
printf "%s = " "$args"
echo "$args" | bc -l
;;
units)
src=$(printf "%s" "$args" | sed 's/ ->.*//')
dst=$(printf "%s" "$args" | sed 's/.*-> //')
units -1 -v -- "$src" "$dst"
;;
*)
exit 1
;;
esac

View File

@ -1,29 +0,0 @@
#!/usr/bin/env python
import re
import sys
import random
if __name__ == '__main__':
roll = sys.argv[1]
m = re.match('^(?P<rolls>\d+)d(?P<sides>\d+)(x(?P<multiplier>\d+))?$', roll)
if m:
rolls = int(m.group('rolls'))
sides = int(m.group('sides'))
if m.group('multiplier'):
multiplier = int(m.group('multiplier'))
else:
multiplier = 1
dice = []
acc = 0
for i in range(rolls):
n = random.randint(1, sides)
dice.append(n)
acc += n
acc *= multiplier
if rolls > 1:
print '%s: %d %r' % (roll, acc, dice)
else:
print '%s: %d' % (roll, acc)

16
run
View File

@ -1,16 +0,0 @@
#! /bin/sh -e
botdir=$1
ircdir=$(dirname $0)
export botdir ircdir
if [ ! -d "$botdir" ]; then
exec 1>&2
echo "Usage: $0 BOTDIRECTORY"
exit 1
fi
while true; do
$botdir/connect $ircdir/connect-handler $botdir
sleep 5
done