Class: Stealth::Controller

Inherits:
Object
  • Object
show all
Includes:
Callbacks, CatchAll, DevJumps, DynamicDelay, Helpers, InterruptDetect, Messages, Nlp, Replies, UnrecognizedMessage
Defined in:
lib/stealth/controller/nlp.rb,
lib/stealth/controller/helpers.rb,
lib/stealth/controller/replies.rb,
lib/stealth/controller/messages.rb,
lib/stealth/controller/callbacks.rb,
lib/stealth/controller/catch_all.rb,
lib/stealth/controller/dev_jumps.rb,
lib/stealth/controller/controller.rb,
lib/stealth/controller/dynamic_delay.rb,
lib/stealth/controller/interrupt_detect.rb,
lib/stealth/controller/unrecognized_message.rb

Direct Known Subclasses

BotController

Defined Under Namespace

Modules: Callbacks, CatchAll, DevJumps, DynamicDelay, Helpers, InterruptDetect, Messages, Nlp, Replies, UnrecognizedMessage

Constant Summary

Constants included from DevJumps

DevJumps::DEV_JUMP_REGEX

Constants included from DynamicDelay

DynamicDelay::LONG_DELAY, DynamicDelay::SHORT_DELAY, DynamicDelay::STANDARD_DELAY

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DynamicDelay

#calculate_delay_from_text

Constructor Details

#initialize(service_message:, pos: nil) ⇒ Controller

Returns a new instance of Controller.



22
23
24
25
26
27
28
29
# File 'lib/stealth/controller/controller.rb', line 22

def initialize(service_message:, pos: nil)
  @current_message = service_message
  @current_service = service_message.service
  @current_session_id = service_message.sender_id
  @nlp_result = service_message.nlp_result
  @pos = pos
  @progressed = false
end

Instance Attribute Details

#action_nameObject (readonly)

Returns the value of attribute action_name.



18
19
20
# File 'lib/stealth/controller/controller.rb', line 18

def action_name
  @action_name
end

#current_messageObject (readonly)

Returns the value of attribute current_message.



18
19
20
# File 'lib/stealth/controller/controller.rb', line 18

def current_message
  @current_message
end

#current_serviceObject (readonly)

Returns the value of attribute current_service.



18
19
20
# File 'lib/stealth/controller/controller.rb', line 18

def current_service
  @current_service
end

#current_session_idObject (readonly)

Returns the value of attribute current_session_id.



18
19
20
# File 'lib/stealth/controller/controller.rb', line 18

def current_session_id
  @current_session_id
end

#flow_controllerObject (readonly)

Returns the value of attribute flow_controller.



18
19
20
# File 'lib/stealth/controller/controller.rb', line 18

def flow_controller
  @flow_controller
end

#nlp_resultObject

Returns the value of attribute nlp_result.



20
21
22
# File 'lib/stealth/controller/controller.rb', line 20

def nlp_result
  @nlp_result
end

#posObject

Returns the value of attribute pos.



20
21
22
# File 'lib/stealth/controller/controller.rb', line 20

def pos
  @pos
end

Instance Method Details

#action(action: nil) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/stealth/controller/controller.rb', line 65

def action(action: nil)
  begin
    # Grab a mutual exclusion lock on the session
    lock_session!(
      session_slug: Session.slugify(
        flow: current_session.flow_string,
        state: current_session.state_string
      )
    )

    @action_name = action
    @action_name ||= current_session.state_string

    # Check if the user needs to be redirected
    if current_session.flow.current_state.redirects_to.present?
      Stealth::Logger.l(
        topic: "redirect",
        message: "From #{current_session.session} to #{current_session.flow.current_state.redirects_to.session}"
      )
      step_to(session: current_session.flow.current_state.redirects_to, pos: @pos)
      return
    end

    run_callbacks :action do
      begin
        flow_controller.send(@action_name)
        unless flow_controller.progressed?
          run_catch_all(reason: 'Did not send replies, update session, or step')
        end
      rescue Stealth::Errors::Halted
        Stealth::Logger.l(
          topic: "session",
          message: "User #{current_session_id}: session halted."
        )
      rescue StandardError => e
        if e.class == Stealth::Errors::UnrecognizedMessage
          run_unrecognized_message(err: e)
        else
          run_catch_all(err: e)
        end
      end
    end
  ensure
    # Release mutual exclusion lock on the session
    release_lock!
  end
end

#current_sessionObject



54
55
56
# File 'lib/stealth/controller/controller.rb', line 54

def current_session
  @current_session ||= Stealth::Session.new(id: current_session_id)
end

#do_nothingObject



219
220
221
# File 'lib/stealth/controller/controller.rb', line 219

def do_nothing
  @progressed = :do_nothing
end

#halt!Object



223
224
225
# File 'lib/stealth/controller/controller.rb', line 223

def halt!
  raise Stealth::Errors::Halted
end

#has_attachments?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/stealth/controller/controller.rb', line 35

def has_attachments?
  current_message.attachments.present?
end

#has_location?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/stealth/controller/controller.rb', line 31

def has_location?
  current_message.location.present?
end

#previous_sessionObject



58
59
60
61
62
63
# File 'lib/stealth/controller/controller.rb', line 58

def previous_session
  @previous_session ||= Stealth::Session.new(
    id: current_session_id,
    type: :previous
  )
end

#progressed?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/stealth/controller/controller.rb', line 39

def progressed?
  @progressed
end

#routeObject



43
44
45
# File 'lib/stealth/controller/controller.rb', line 43

def route
  raise(Stealth::Errors::ControllerRoutingNotImplemented, "Please implement `route` method in BotController")
end

#set_back_to(session: nil, flow: nil, state: nil, slug: nil) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/stealth/controller/controller.rb', line 187

def set_back_to(session: nil, flow: nil, state: nil, slug: nil)
  if interrupt_detected?
    run_interrupt_action
    return :interrupted
  end

  flow, state = get_flow_and_state(
    session: session,
    flow: flow,
    state: state,
    slug: slug
  )

  store_back_to_session(flow: flow, state: state)
end

#step_backObject



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/stealth/controller/controller.rb', line 203

def step_back
  back_to_session = Stealth::Session.new(
    id: current_session_id,
    type: :back_to
  )

  if back_to_session.blank?
    raise(
      Stealth::Errors::InvalidStateTransition,
      'back_to_session not found; make sure set_back_to was called first'
    )
  end

  step_to(session: back_to_session)
end

#step_to(session: nil, flow: nil, state: nil, slug: nil, pos: nil) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/stealth/controller/controller.rb', line 155

def step_to(session: nil, flow: nil, state: nil, slug: nil, pos: nil)
  if interrupt_detected?
    run_interrupt_action
    return :interrupted
  end

  flow, state = get_flow_and_state(
    session: session,
    flow: flow,
    state: state,
    slug: slug
  )

  step(flow: flow, state: state, pos: pos)
end

#step_to_at(timestamp, session: nil, flow: nil, state: nil, slug: nil) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/stealth/controller/controller.rb', line 134

def step_to_at(timestamp, session: nil, flow: nil, state: nil, slug: nil)
  if interrupt_detected?
    run_interrupt_action
    return :interrupted
  end

  flow, state = get_flow_and_state(
    session: session,
    flow: flow,
    state: state,
    slug: slug
  )

  unless timestamp.is_a?(DateTime)
    raise ArgumentError, "Please specify your step_to_at `timestamp` parameter as a DateTime"
  end

  Stealth::ScheduledReplyJob.perform_at(timestamp, current_service, current_session_id, flow, state, current_message.target_id)
  Stealth::Logger.l(topic: "session", message: "User #{current_session_id}: scheduled session step to #{flow}->#{state} at #{timestamp.iso8601}")
end

#step_to_in(delay, session: nil, flow: nil, state: nil, slug: nil) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/stealth/controller/controller.rb', line 113

def step_to_in(delay, session: nil, flow: nil, state: nil, slug: nil)
  if interrupt_detected?
    run_interrupt_action
    return :interrupted
  end

  flow, state = get_flow_and_state(
    session: session,
    flow: flow,
    state: state,
    slug: slug
  )

  unless delay.is_a?(ActiveSupport::Duration)
    raise ArgumentError, "Please specify your step_to_in `delay` parameter using ActiveSupport::Duration, e.g. `1.day` or `5.hours`"
  end

  Stealth::ScheduledReplyJob.perform_in(delay, current_service, current_session_id, flow, state, current_message.target_id)
  Stealth::Logger.l(topic: "session", message: "User #{current_session_id}: scheduled session step to #{flow}->#{state} in #{delay} seconds")
end

#update_session_to(session: nil, flow: nil, state: nil, slug: nil) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/stealth/controller/controller.rb', line 171

def update_session_to(session: nil, flow: nil, state: nil, slug: nil)
  if interrupt_detected?
    run_interrupt_action
    return :interrupted
  end

  flow, state = get_flow_and_state(
    session: session,
    flow: flow,
    state: state,
    slug: slug
  )

  update_session(flow: flow, state: state)
end