A Joan Follow Up

ai, ruby

I have to say, the internet is pretty awesome. Having just posted the final code for my Joan bot – my first foray into Ruby – this morning I received an e-mail with a source code rewrite for Joan.

So why does that make the internet so awesome? Because it’s been less than two days from getting the post out, to getting better source code. I’m able to improve my Ruby skills with a little help from others and you get a great script for making bots! Everyone wins which is the point of this blog endeavor.

Less talk, more code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Usage: $ ruby joan.rb [num iterations]
require 'net/http'

class Bot
  URL = URI.parse('http://jabberwacky.icogno.com/webserviceform-joan')

  def initialize(name)
    @name = name
  end

  def respond(message = nil)
    @data.nil? ? start_conversation : post(message)

    response = @data["ttsText"]
    puts "#{@name}: #{response}"
    STDOUT.flush
    response
  end

  private

  def post(message)
    @data['STIMULUS'] = message
    @data['sub']  = 'Say'
    get_response { Net::HTTP.post_form(URL, @data) }
  end

  def start_conversation
    get_response { Net::HTTP.get_response(URL) }
  end

  # Retrieve all the variables and setup as a hash for doing a POST
  def get_post_variables
    @data = {}
    @response_text
    .scan(/NAME=(\w+) TYPE=hidden VALUE="([^"]*)/) do |name, value|
      @data[name] = value
    end
  end

  def get_response
    trials = 3 # Try three times -- sometimes calls fail
    response = begin
                 yield
               rescue
                 trials -= 1
                 trials > 0 ?
                  retry :
                  raise("Did not receive response after 3 attempts")
               end

    @response_text = response.body
    get_post_variables
  end
end

bots = %w{perl ruby}.map { |name| Bot.new(name) }

last_message = nil
(ARGV[0] || 10).to_i.times do
  bots.each { |bot| last_message = bot.respond(last_message) }
end

Feel free to download Joan’s Ruby script for yourself. Thanks to Brent for the updated source code.

And now to figure out what all that Ruby magic is…

This page was delicately crafted on by Gavin Miller.