class BotFramework::Session
Attributes
Public Class Methods
Returns a active stack entry or nil
# File lib/bot_framework/session.rb, line 331 def self.active_dialog_stack_entry(stack) stack.last || nil end
Searches a dialog stack for a specific dialog, in either a forward or reverse direction, returning its index.
# File lib/bot_framework/session.rb, line 323 def self.findEachDialogStackEntry(stack, dialog_id) stack.each_with_index do |item, index| return index if item[:id] = dialog_id end -1 end
Enumerates all a stacks dialog entries in either a forward or reverse direction.
# File lib/bot_framework/session.rb, line 318 def self.forEachDialogStackEntry(stack) stack.each { |item| yield(item) } end
# File lib/bot_framework/session.rb, line 5 def initialize(options) super @library = options[:library] @localizer = options[:localizer] @msg_sent = false @is_reset = false @last_send_time = Time.now # TODO: Move to proc? @batch = [] @batch_timer = Timers::Group.new @batch_started = false @sending_batch = false @in_middleware = false @_locale = nil @options = options || { on_save: nil, on_send: nil, library: nil, localizer: nil, middleware: nil, dialog_id: nil, dialog_args: nil, auto_batch_delay: nil, dialog_error_message: nil, actions: nil } @auto_batch_delay = 250 unless options[:auto_batch_delay].is_a? Integer @timers = Timers::Group.new end
Pop active dialog out of the stack
# File lib/bot_framework/session.rb, line 344 def self.pop_dialog_stack_entry(stack) stack.pop if stack Session.active_dialog_stack_entry(stack) end
Deletes all dialog stack entries starting with the specified index and returns the new active dialog.
# File lib/bot_framework/session.rb, line 350 def self.prune_dialog_stack(_stack, _start) end
Pushes a new dialog into stack and return it as active dialog
# File lib/bot_framework/session.rb, line 336 def self.push_dialog_stack_entry(statck, entry) entry[:state] ||= {} statck ||= [] stack.push(entry) entry end
Ensures that all of the entries on a dialog stack reference valid dialogs within a library hierarchy.
# File lib/bot_framework/session.rb, line 354 def self.validate_dialog_stack(_stack, _root) end
Public Instance Methods
Begin a new dialog
# File lib/bot_framework/session.rb, line 188 def begin_dialog(id, args = nil) logger.info "Beginning new dialog #{id}" id = resolve_dialog_id(id) dialog = find_dialog(id) raise "Dialog #{id} Not found" unless dialog push_dialog(id: id, state: {}) start_batch dialog.begin(self, args) self end
# File lib/bot_framework/session.rb, line 290 def cancel_dialog; end
Clears the current Dialog stack
# File lib/bot_framework/session.rb, line 312 def clear_dialog_stack @session_state[:call_stack] = [] @dialog_data = nil end
Gets and Sets current dialog stack
# File lib/bot_framework/session.rb, line 297 def dialog_stack(new_stack = nil) if new_stack # Update stack and dialog data stack = @session_state[:call_stack] = new_stack || [] @dialog_data = stack.empty? nil || stack.last else # Copy over dialog data to slack stack = @session_state[:call_stack] || [] stack.last.state = @dialog_data || {} end stack end
# File lib/bot_framework/session.rb, line 50 def dispatch(session_state, message) index = 0 session = self now = Time.now middleware = @options[:middleware] || [] _next = lambda do handler = middleware[index] if index < middleware.length if handler index += 1 handler(session, _next) else @in_middleware = false @session_state[:last_acess] = now done end end session_state ||= { call_stack: [], last_acess: Time.now, version: 0.0 } # Making sure that dialog is properly initialized cur = cur_dialog self.dialog_data = cur.state if cur # Dispatch message message ||= { text: '' } message[:type] ||= 'message' # Ensure that localized prompts are loaded # TODO self end
End conversation with the user
# File lib/bot_framework/session.rb, line 214 def end_conversation(message = nil, _args = {}) if message # TODO: sent message end # Clear private conversation data @private_conversation_data = {} # Clear stack and save logger.info 'End conversation' ss = @session_state ss.call_stack = [] send_batch self end
# File lib/bot_framework/session.rb, line 229 def end_dialog(message = nil, args = {}) if message # TODO: end_dialog_with_result end cur = cur_dialog if cur if message m = if (message.is_a? String) || (message.is_a? Array) create_message(cur_library_name, message, args) else message end @msg_sent = true prepare_message(m) @batch.push(m) end # Pop the dialog of the stack and resume the parent logger.info 'Session.end_dialog' child_id = cur.id cur = pop_dialog start_batch if cur dialog = find_dialog(cur.id) if dialog dialog.dialog_resumed(self, resumed: :completed, response: true, child_id: child_id) else # Bad dialog !! , we should never reach here raise "Can't resume , missing parent" end end end end
Ends current dialog and returns a value to the caller
# File lib/bot_framework/session.rb, line 264 def end_dialog_with_result(result) # Validate call stack cur = cur_dialog if cur # Validate the result result ||= {} result[:resumed] ||= :completed result.child_id = cur.id logger.info 'Session.end_dialog_with_result' # Pop dialog of the stack and resume parent dialog cur = pop_dialog start_batch if cur dialog = find_dialog(cur.id) if dialog dialog.dialog_resumed(self, result) else # Bad dialog state raise "Can't resume , missing parent dialog" end end end self end
# File lib/bot_framework/session.rb, line 79 def error(_error) logger.info 'Session error' if options[:dialog_error_message] end_conversation(options[:dialog_error_message]) else # TODO: Add localisation locale = preferred_locale end_conversation 'Error in conversation' end # TODO: Log error end
Gets and formats localized text string
# File lib/bot_framework/session.rb, line 110 def gettext(message_id, options = {}) # TODO # stub end
Gets and formats the singular/plural form of a localized text string.
# File lib/bot_framework/session.rb, line 116 def ngettext(message_id, message_id_plural, count); end
# File lib/bot_framework/session.rb, line 92 def preferred_locale(locale = nil) if locale @_locale = locale @user_data['BotBuilder.Data.PreferredLocale'] = locale if @user_data @localizer.load if @localizer # TODO elsif !@_locale if @user_data && @user_data['BotBuilder.Data.PreferredLocale'] @_locale = @user_data['BotBuilder.Data.PreferredLocale'] elsif @message && @message[:text_locale] @_locale = @message[:text_locale] elsif @localizer @_locale = @localizer[:default_locale] end end @_locale end
# File lib/bot_framework/session.rb, line 199 def replace_dialog(id, args = nil) logger.info "Session replace dialog #{id}" id = resolve_dialog_id(id) dialog = find_dialog(id) raise "Dialog #{id} Not found" unless dialog # Update the stack and start dialog pop_dialog push_dialog(id: id, state: {}) start_batch dialog.begin(self, args) self end
# File lib/bot_framework/session.rb, line 292 def reset; end
Dispatches handling of the current message to the active dialog stack entry.
# File lib/bot_framework/session.rb, line 361 def route_to_active_dialog; end
Manually save current session state
# File lib/bot_framework/session.rb, line 119 def save logger.info 'Session.save' start_batch self end
# File lib/bot_framework/session.rb, line 125 def send(message, args = []) args.unshift(@cur_library_name, message) send_localized(args, message) end
# File lib/bot_framework/session.rb, line 149 def send_batch logger.info "Sending batch with elements #{@batch.count}" return if sending_batch? # TODO: timer @batch_timer = nil batch = @batch @batch_started = false @sending_batch = true cur = cur_dialog cur.state = @dialog_data options[:on_save] = proc do |err| if err @sending_batch = false case (err.code || '') when 'EBADMSG' when 'EMSGSIZE' # Something went wrong , let's reset everything @user_data = {} @batch = [] end_conversation(@options[:dialog_error_message] || 'Something went wrong and we need to startover') end yield(err) if block_given? else if batch.length options[:on_send].call(batch) do |err| @sending_batch = false start_batch if @batch_started # What is this :o yield(err) if block_given? end else @sending_batch = false start_batch if @batch_started yield(err) if block_given? end end end end
# File lib/bot_framework/session.rb, line 130 def send_localized(_localization_namspace, message, _args = []) # TODO: Incomplete @msg_sent = true m = { text: message } prepare_message(m) @batch << m self end
Sends a typing indicator to the user
# File lib/bot_framework/session.rb, line 140 def send_typing @msg_sent = true m = { type: 'typing' } m = prepare_message(m) @batch.push(m) logger.info 'Send Typing' send_batch end
# File lib/bot_framework/session.rb, line 35 def to_recognize_context { message: message, user_data: user_data, conversation_data: conversation_data, private_conversation_data: private_conversation_data, localizer: localizer, dialog_stack: dialog_stack, preferred_locale: preferred_locale, get_text: get_text, nget_text: nget_text, locale: preferred_locale } end
Private Instance Methods
# File lib/bot_framework/session.rb, line 376 def create_message; end
# File lib/bot_framework/session.rb, line 401 def cur_dialog ss = @session_sate cur = ss.call_stack.last unless ss.call_stack.empty? cur end
# File lib/bot_framework/session.rb, line 391 def cur_library_name; end
# File lib/bot_framework/session.rb, line 399 def delete_dialogs; end
# File lib/bot_framework/session.rb, line 393 def find_dialog; end
# File lib/bot_framework/session.rb, line 397 def pop_dialog; end
# File lib/bot_framework/session.rb, line 378 def prepare_message(msg) msg[:type] ||= 'message' msg[:address] ||= message[:address] msg[:text_locale] ||= message[:text_locale] msg end
# File lib/bot_framework/session.rb, line 395 def push_dialog; end
# File lib/bot_framework/session.rb, line 389 def resolve_dialog_id; end
# File lib/bot_framework/session.rb, line 365 def start_batch @batch_started = true unless @sending_batch @batch_timer.cancel if @batch_timer # TODO: send_batch after config[:auto_batch_delay] seconds @batch_timer = @timers.after(config[:auto_batch_delay]) do send_batch end end end
# File lib/bot_framework/session.rb, line 387 def validate_call_stack; end
# File lib/bot_framework/session.rb, line 385 def vget_text; end