| So, the guys over at suckless.org have created a neat little program called ii
(http://tools.suckless.org/ii) which provides a filesystem-based interface to
irc, perfect for writing simple bots on top of. As an exercise in making
something of (relatively) practical use in arc, I decided to hook arc up to ii
and write a simple irc bot. To do this, I first had to connect arc to ii. This
turned out to be not too difficult, although it does require some things not
exposed in base arc, so I make use of my $ hack to access the underlying
mzscheme. As it's a bit long to post here, the file `ii.arc` which contains the code
interfacing arc to ii is available at http://www.rntz.net/files/ii-0.arc . I've
also put up a (world-readable) darcs repository at
http://www.rntz.net/darcs/arc/iibot. In addition to ii.arc, there's a file
bot.arc which contains the bot I'm working on; its present contents (available
at http://www.rntz.net/files/bot-0.arc) serve as a fairly good example of how to
use the ii interface, and I'll post them here: (def rot13c (c)
(with (i (coerce c 'int)
ai (coerce #\a 'int)
Ai (coerce #\A 'int))
(let offset (if (<= ai i (+ ai 26)) ai
(<= Ai i (+ Ai 26)) Ai)
(if no.offset c
(coerce (+ (mod (+ (- i offset) 13) 26) offset) 'char)))))
(def rot13 (s) (map rot13c s))
(= default-chans* '("#rntztest")
default-nick* "bot-of-rntz")
(def start ((o nick default-nick*))
(= nick* nick)
(ii-start ii-default-dir* ii-default-server* nick))
(def ii-nick (newnick)
(ii "/n @newnick")
(= nick* newnick))
(def run chans
(or= chans default-chans*)
(ii-spawnbot (fn _ (apply handle _)) chans))
(def die () (kill-thread ii-tid*))
(def stop () (die) (ii-stop))
(def handle (msg)
(unless (or (is msg!from nick*) ;ignore our own messages
(~begins msg!text ","))
(prn "handling: @(msg 'from): @msg!text")
(let (cmd args) (map [cut _ 1] (halve msg!text))
(case sym.cmd
rot13 (ii-send msg!chan (+ msg!from ": " rot13.args))
echo (ii-send msg!chan (+ msg!from ": " args))
; else
(w/stdout (stderr)
(prn "unknown command: @cmd"))))))
An example of interactive use: arc> (map load '("bot.arc" "ii.arc"))
(nil nil)
arc> (start)
(#<input-port:subprocess-stdout> #<output-port:subprocess-stdin> 16648 #<input-port:subprocess-stderr> #<procedure:control>)
; at this point, ii is running, but the bot is not
arc> (run)
#<thread: ii-tid*>
; at this point, the bot has joined the relevant channels and responds to commands
arc> (die)
#<void>
; at this point, the bot is no longer running but ii is still connected
arc> (stop)
; now ii itself is no longer connected
An example of interacting with the bot on irc: < rntz> ,echo this is a test
< bot-of-rntz> rntz: this is a test
< rntz> ,rot13 V ybir nep
< bot-of-rntz> rntz: I love arc
|