Minion-bot for AIM
Tuesday, February 15, 2005
I've been meanting to try out
John Wiseman's CLAIM package for some time now.
CLAIM is a CL package that
provides an interface to
AOL Instant Messenger (AIM). In order to do
something more interesting than just running John's demo programs, I
decided to write an
Eliza-bot for AIM. There are a number of Eliza implementations
available for CL, but I chose to use one that will be familiar to
anyone who has visited the #lisp IRC channel - Minion.
Minion is an IRC bot that was written by
Brian Mastenbrook (who usually goes by the handle "chandler" on
the #lisp IRC channel) and is part of the
CL-IRC package (it's in the "example" directory). Minion has a
bit of an "attitude" and combines both some useful functionality with an
Eliza-like personality.
I combined the CLAIM package with
the Eliza-like components of Minion to create an AIM Minion-bot. The following screen shows the
result:

To re-create what I did, you will need to:
- Download John Wiseman's
CLAIM AIM package, Edi Weitz's
CL-PPCRE regex package, and the following files from the
cl-irc
cvs:
- eliza-rules.lisp
- mp2eliza.lisp
- Create the following minion-bot.lisp file and put it in the
"minion-bot" directory:
;;; A version of the Minion IRC bot for AIM, using CLAIM.
(defpackage :minion-bot (:use :common-lisp :com.lemonodor.claim :eliza) (:export #:start-minion-bot))
(in-package :minion-bot)
(defun start-minion-bot (username password) (let ((bot (make-instance 'minion-bot :username username :password password))) (open-aim-connection bot) (unwind-protect (receive-events bot) (close-aim-connection bot))))
(defclass minion-bot (aim-connection) ((messages :accessor messages :initform '()) (users :accessor users :initform nil)))
(defmethod handle-im-in ((self minion-bot) user auto-p message) (declare (ignore auto-p)) (format T "~&~A: ~A" user (strip-msg message)) (if (not (member user (users self) :test #'equalp)) (do-send-im self user (format nil "Hi, ~A. I'm a Lisp bot based on the IRC Minion bot. What's up?" user)) (do-send-im self user (format nil "~A" (eliza::print-with-spaces (eliza::flatten (eliza::use-eliza-rules (eliza::read-line-no-punct (strip-msg message)))))))) (pushnew user (users self) :test #'equal))
(defmethod do-send-im :around ((self minion-bot) user message &key (auto-p)) (declare (ignore user auto-p)) (format T "~&~A: ~A" (aim-connection-username self) message) (call-next-method))
(defmethod handle-warned ((self minion-bot) warn-level warner) (declare (ignore warn-level)) (do-send-im self warner "I bet that made you feel tough.") (if (zerop (random 2)) (do-warn self warner NIL)))
(defun strip-msg (msg) (multiple-value-bind (found-p res) (cl-ppcre:scan-to-strings ".*<font .*>(.*)</font></body></html>" msg) (if found-p (aref res 0)))) - Create the following ASDF definition minion-bot.asd file and put
it in the "minion-bot" directory:
(in-package #:cl-user)
(defpackage #:minion-bot-system (:use #:cl #:asdf))
(in-package #:minion-bot-system)
(defsystem :minion-bot :name "minion-bot" :author "Bill Clementson" :version "0.1" :licence "MIT" :description "Minion bot for CLAIM" :depends-on (:claim :cl-ppcre) :components ((:file "mp2eliza") (:file "eliza-rules" :depends-on ("mp2eliza")) (:file "minion-bot" :depends-on ("mp2eliza")))) - Make certain the CLAIM, CL-PPCRE, and MINION-BOT directories are all in your asdf:*central-registry* variable and use asdf to build the minion-bot.asd file (it will build the CLAIM and CL-PPCRE dependent libraries as well).
(minion-bot:start-minion-bot "myusername" "mypassword")

