There was a post on Reddit the other day about using Python to get Cleverbot to respond to incoming IMs. It looked like an interesting hack, but it used Python, Pidgin and D-Bus, none of which I have on hand right now… so I made something similar using Groovy, Selenium and Smack.
You can have it wait for someone to IM you, or you can tell it to troll someone on startup; either way, it automatically saves the chat transcript to disk on shutdown. Here’s the code:
@Grapes([ @Grab('org.igniterealtime.smack:smack:3.2.1'), @Grab('org.igniterealtime.smack:smackx:3.2.1'), @Grab('org.seleniumhq.selenium:selenium-firefox-driver:2.5.0'), @Grab('org.seleniumhq.selenium:selenium-support:2.5.0')]) import org.jivesoftware.smack.XMPPConnection import org.jivesoftware.smack.ChatManagerListener import org.jivesoftware.smack.MessageListener import org.jivesoftware.smack.Chat import org.openqa.selenium.firefox.FirefoxDriver import org.openqa.selenium.support.ui.WebDriverWait import org.openqa.selenium.By import com.google.common.base.Predicate import java.util.concurrent.TimeUnit import groovy.ui.SystemOutputInterceptor if(args.length < 3 || args.length > 4) { println 'Usage: groovy chat.groovy server username password [userToTroll]' return } def oldSendMessage = Chat.metaClass.getMetaMethod('sendMessage', [String] as Class[]) Chat.metaClass.sendMessage = { String s -> println "cleverbot/me: $s" oldSendMessage.invoke(delegate, s); } def transcript = '' new SystemOutputInterceptor({ transcript += it; true; }).start() def driver = new FirefoxDriver() driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS) driver.get 'http://www.cleverbot.com/' def conn = new XMPPConnection(args[0]) conn.connect() conn.login(args[1], args[2]) def messageListener = { chat, message -> println "$message.from: $message.body" def response = say message.body, driver chat.sendMessage response } as MessageListener def chatListener = { chat, createdLocally -> chat.addMessageListener messageListener } as ChatManagerListener conn.chatManager.addChatListener chatListener addShutdownHook { driver.quit() conn.disconnect() new File('transcript.txt').write transcript } if(args.length >= 4) { def chat = conn.chatManager.createChat(args[3], null) chat.sendMessage 'Hey!' } while(true) { Thread.sleep 1000 } def say(input, driver) { def field = driver.findElement(By.id('stimulus')) field.sendKeys input field.submit() def response = null def condition = { def element = driver.findElement(By.id('typArea')) def finished = (response == element.text && !['', '|'].contains(element.text)) response = element.text return finished } as Predicate def wait = new WebDriverWait(driver, 30).until(condition) return response }
Here’s the first conversation it had with my brother:
cleverbot/me: Hey!
my brother: sup?
cleverbot/me: What?
my brother: huh?
cleverbot/me: Never mind.
Never mind?!? Come on, Cleverbot! You can do better than that! Let’s try again.
cleverbot/me: Hey!
my brother: sup?
cleverbot/me: Sep.
At this point my brother called me on the phone to ask what I was smoking… I didn’t pick up. Third time’s the charm, right? I tried again, tweaking the initial message to try to draw him into a conversation.
cleverbot/me: did you just call?
my brother: yeah
cleverbot/me: Yeah yeah yeah.
[ed.: this isn’t looking so good…]
my brother: was seeing why you’re acting all goofy
cleverbot/me: Did you know what a hijab is?
[ed.: wha? where did that come from?]
my brother: but seriously, when i get the number from the sheet, if there is a 0 at the beginning it’s not included
cleverbot/me: But you continue to lie. You are a computer. You do not get up in the morning, you don’t look in the mirror… You can’t feel… And I feel sorry for you.
[ed.: facepalm…]
my brother: and your sheet won’t bring back values, so i fixed it but have to use an “if” statement which won’t work with your macro
cleverbot/me: Okay.
Okay, indeed. Bah. My brother was asking serious questions about a script I wrote for him, and all Cleverbot could think to talk about was hijabs and chatbot philosophy.
I think I’ll answer my own IMs… for now.