class Lita::Wizard

Attributes

current_step_index[RW]
id[RW]
message[RW]
meta[RW]
robot[RW]
user_id[RW]
values[RW]

Public Class Methods

cancel_wizard(user_id) click to toggle source
# File lib/lita/wizard.rb, line 188
def cancel_wizard(user_id)
  Lita.redis.del "pending-wizard-#{user_id.downcase}"
end
handle_message(robot, message) click to toggle source
# File lib/lita/wizard.rb, line 164
def handle_message(robot, message)
  return false unless pending_wizard?(message.user.id)
  wizard = restore(robot, message)
  if wizard
    wizard.handle_message
    true
  else
    cancel_wizard(message.user.id)
    false
  end
end
new(robot, message, data = {}) click to toggle source
# File lib/lita/wizard.rb, line 7
def initialize(robot, message, data = {})
  @id = data['id'] || SecureRandom.hex(3)
  @robot = robot
  @message = message
  @user_id = message.user.id
  @current_step_index = (data['current_step_index'] || -1).to_i
  @values = data['values'] || []
  @meta = data['meta']
end
pending_wizard?(user_id) click to toggle source
# File lib/lita/wizard.rb, line 184
def pending_wizard?(user_id)
  Lita.redis["pending-wizard-#{user_id.downcase}"]
end
restore(robot, message) click to toggle source
# File lib/lita/wizard.rb, line 176
def restore(robot, message)
  data = MultiJson.load(Lita.redis["pending-wizard-#{message.user.id.downcase}"])
  klass = eval(data['class'])
  klass.new(robot, message, data)
rescue
  nil
end
start(robot, message, meta = {}) click to toggle source
# File lib/lita/wizard.rb, line 157
def start(robot, message, meta = {})
  return false if pending_wizard?(message.user.id)
  wizard = new(robot, message, 'meta' => meta)
  wizard.advance
  true
end
step(name, options = {}) click to toggle source
# File lib/lita/wizard.rb, line 192
def step(name, options = {})
  steps << OpenStruct.new(options.merge(name: name))
end
steps() click to toggle source
# File lib/lita/wizard.rb, line 196
def steps
  @steps ||= []
end

Public Instance Methods

abort_message() click to toggle source
# File lib/lita/wizard.rb, line 133
def abort_message
  "Aborting. Resume your normal operations"
end
abort_wizard() click to toggle source
# File lib/lita/wizard.rb, line 144
def abort_wizard
end
advance() click to toggle source
# File lib/lita/wizard.rb, line 17
def advance
  self.current_step_index += 1
  save
  if final_step?
    finish_wizard
    send_message final_message
    destroy
  elsif run_current_step?
    if first_step?
      start_wizard
      send_message initial_message
    end
    message = step[:label]
    message = "#{message} (Write done when finished)" if step[:multiline]
    send_message message
  else
    advance
  end
end
as_json() click to toggle source
# File lib/lita/wizard.rb, line 77
def as_json
  {
    'class' => self.class.name,
    'id' => id,
    'user_id' => user_id,
    'current_step_index' => current_step_index,
    'values' => values,
    'meta' => meta
  }
end
destroy() click to toggle source
# File lib/lita/wizard.rb, line 69
def destroy
  Lita.redis.del "pending-wizard-#{user_id.downcase}"
end
final_message() click to toggle source
# File lib/lita/wizard.rb, line 137
def final_message
  "You're done!"
end
final_step?() click to toggle source
# File lib/lita/wizard.rb, line 100
def final_step?
  current_step_index == steps.size
end
finish_wizard() click to toggle source
# File lib/lita/wizard.rb, line 147
def finish_wizard
end
first_step?() click to toggle source
# File lib/lita/wizard.rb, line 104
def first_step?
  current_step_index == 0
end
handle_message() click to toggle source
# File lib/lita/wizard.rb, line 37
def handle_message
  if message.body == "abort"
    send_message abort_message
    abort_wizard
    destroy
  elsif step.nil?
    send_message "Some error occured. Aborting."
    destroy
  elsif message.body == "done" && step[:multiline]
    save
    advance
  elsif valid_response?
    if step[:multiline]
      values[current_step_index] ||= ""
      values[current_step_index] << "\n"
      values[current_step_index] << message.body
      values[current_step_index].strip!
      save
    else
      values[current_step_index] = message.body
      save
      advance
    end
  else
    send_message @error_message
  end
end
initial_message() click to toggle source
# File lib/lita/wizard.rb, line 128
def initial_message
  "Great! I'm going to ask you some questions. During this time I cannot take regular commands. " \
  "You can abort at any time by writing abort"
end
run_current_step?() click to toggle source
# File lib/lita/wizard.rb, line 96
def run_current_step?
  step[:if].nil? || instance_eval(&step[:if])
end
save() click to toggle source
# File lib/lita/wizard.rb, line 65
def save
  Lita.redis["pending-wizard-#{user_id.downcase}"] = to_json
end
send_message(body) click to toggle source
# File lib/lita/wizard.rb, line 150
def send_message(body)
  # Wizard must run in a private chat versus a room
  message.reply_privately body
end
start_wizard() click to toggle source
# File lib/lita/wizard.rb, line 141
def start_wizard
end
step() click to toggle source
# File lib/lita/wizard.rb, line 88
def step
  steps[current_step_index]
end
step_index(step_name) click to toggle source
# File lib/lita/wizard.rb, line 112
def step_index(step_name)
  steps.index { |step| step.name == step_name }
end
steps() click to toggle source
# File lib/lita/wizard.rb, line 92
def steps
  self.class.steps
end
to_json() click to toggle source
# File lib/lita/wizard.rb, line 73
def to_json
  MultiJson.dump(as_json)
end
valid_response?() click to toggle source
# File lib/lita/wizard.rb, line 116
def valid_response?
  if step[:validate] && !step[:validate].match(message.body)
    @error_message = 'Invalid format'
    false
  elsif step[:options] && !step[:options].include?(message.body)
    @error_message = "Invalid response. Valid options: #{step[:options].join(', ')}"
    false
  else
    true
  end
end
value_for(step_name) click to toggle source
# File lib/lita/wizard.rb, line 108
def value_for(step_name)
  values[step_index(step_name)]
end