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.