How to make a chat bot
Jan. 15th, 2008 09:53 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
For various reasons, I wanted a chat bot. I'll get to exactly why later (once it's designed, if not finished), but given my last post, obviously I was going to write it in Script.
This will be a dual-purpose post. It will be a good manual/tutorial for my (unnamed) bot framework, and it will be a complement to the last post. If you found that one to be too much philosophy and not enough code, then this one should be much better.
Getting what you needFirst, install Java. If you have a Mac, (or Linux, probably) you don't have to. In fact, if you have Windows, you probably already have.
You can skip the rest of this step if you want. Downloading the bot framework has all this.
Now, go download Rhino. It is a single JAR file, js.jar. Open a console and type this:
java -classpath js.jar org.mozilla.javascript.tools.shell.Main
You should see this:
js>
Hooray! It's a REPL! If you're on a Mac, the command history won't work. Sorry about that, but there is a quick cure: go download JLine and run this instead:
java -classpath js.jar:jline.jar jline.ConsoleRunner org.mozilla.javascript.tools.shell.Main
You should probably put that in a script somewhere. Call it repl
. Now you can run Rhino whenever you feel like it.
Go grab this. Opening it up, we see a pre-made repl
script, the JAR files, 'bot-framework.js', and a few example bots. 'smack.jar' and 'smackx.jar' are the Smack library, which is what I'm using to talk to Jabber. Let's open a new file and make a bot.
Our bot will be really simple, just parrot anything you say to it back to you. First, you will need a second Google Talk account, for the bot. Go sign up for one and then come back here, I'll wait.
Now, open a new file in your favorite text editor, call it "parrot.js". Write the following into it:
var USER='yourUsername'; var PASS='yourPassword'; function responder(username){ return function(message){ return "Hey there, you said "+message; }; }
Write your actual username (without the @gmail.com part) and your actual password in there, of course. I'll explain that all in a minute. For right now, go back to your console, and run the repl
that came in rossbot.tar.gz. At the js>
prompt, type:
load('bot-framework.js'); load('parrot.js'); var logout=gtBot(USER,PASS,responder);
The load('whatever.js');
part reads files in and runs them. Whenever you change a file, you should load()
it again.
And you should see... Nothing at all happen. Then, send a message to the GTalk account you just made. The console window will say something like "New client your.name@gmail.com/Adium23451A87, making new chatter" and then you should instantly get a message back from yourself saying "Hey there, you said whatever it was you said".
So what did we just do there? The framework has only one function. gtBot
is a function that takes three arguments. The first two are the username and password to a GTalk account (only GTalk right now, any Jabber later). The second is a "responder maker", a function that takes a username and returns a function. That function takes a message, and returns a response. The gtBot
function also returns a function, which logs out of the connection when called (this provides a clean way to shut the bot down, but you can also just kill the Rhino process).
Here's how it works: The first time your bot gets a message from someone, it calls your responder with their name. Your responder returns a function, which the bot remembers as belonging to that client. From then on, the bot passes every message from that client to that function, and sends back whatever it returns. Super-simple, huh?
There are two more advanced tricks you can do. One is the "connection wrapper". This allows you to send messages to more than one person, or to send more than one message. Later on it will allow you to ignore people, go into "away" mode, all sorts of things. Try replacing the 'responder' function with this:
function responder(username){ return function(message,wrapper){ wrapper.sendMessage('ross.andrews@gmail.com', 'Psst! '+username+' said '+message); return 'You said '+message+', and I am telling!'; }; }
It'll do exactly what it looks like. It'll spam me with anything your bot receives. There is one other thing you can do, also, called a "continuation bot", that will probably be much more useful later on. I'm not going to go into much detail on this now; if you don't know what a continuation is, you won't learn it from this. But, try this:
function responder(username,suspend){ return function(message){ var second=suspend('First you said '+message); var third=suspend('Then you said '+second); return 'Finally you said '+third+', and I finished.'; }; }
(You'll need to start this one with logout=gtContinuationBot(USER,PASS,responder);
. Just gtBot won't cut it.)
Send it a few messages, and you'll see that what it's doing is pausing the function in between each one. suspend
is a function that freezes your current program, sends the client a message, gets a response, and then jumps right back into where it left off. It can be a better way to express some functions.
So that's how to write a chat bot. Think of the possibilities: a personal appointment manager that people can message to add things to your calendar. If you built in a password system (easy), you could use it as a simple remote shell client (that works if you don't know your IP address). Build it into a large application to monitor things, or to remotely restart it or inject code.
Or you could do what I'm going to do, but that's not finished yet.