lib/telegram/bot/updates_controller/message_context.rb in telegram-bot-0.13.1 vs lib/telegram/bot/updates_controller/message_context.rb in telegram-bot-0.14.0

- old
+ new

@@ -1,98 +1,77 @@ module Telegram module Bot class UpdatesController # Allows to store context in session and treat next message according to this context. + # + # It provides `save_context` method to store method name + # to be used as action for next update: + # + # def set_location!(*) + # save_context(:set_location_from_message) + # respond_with :message, text: 'Where are you?' + # end + # + # def set_location_from_messge(city = nil, *) + # # update + # end + # + # # OR + # # This will support both `/set_location city_name`, and `/set_location` + # # with subsequent refinement. + # def set_location!(city = nil, *) + # if city + # # update + # else + # save_context(:set_location!) + # respond_with :message, text: 'Where are you?' + # end + # end module MessageContext extend ActiveSupport::Concern include Session - module ClassMethods - def context_handlers - @_context_handlers ||= {} - end - - # Registers handler for context. - # - # context_handler :rename do |*| - # resource.update!(name: payload['text']) - # end - # - # # To run other action with all the callbacks: - # context_handler :rename do |*words| - # process(:rename, *words) - # end - # - # # Or just - # context_handler :rename, :your_action_to_call - # context_handler :rename # to call :rename - # - def context_handler(context = nil, action = nil, &block) - context &&= context.to_sym - if block - action = "_context_handler_#{context}" - define_method(action, &block) - end - context_handlers[context] = action || context - end - - attr_reader :context_to_action - - # Use it to use context value as action name for all contexts - # which miss handlers. - # For security reasons it supports only action methods and will - # raise AbstractController::ActionNotFound if context is invalid. - def context_to_action! - @context_to_action = true - end - end - # Action to clear context. - def cancel + def cancel! # Context is already cleared in action_for_message end private - # Context is read from the session to treat messages - # according to previous request. - attr_reader :context - # Controller may have multiple sessions, let it be possible # to select session for message context. def message_context_session session end # Fetches context and finds handler for it. If message has new command, # it has higher priority than contextual action. def action_for_message val = message_context_session.delete(:context) - @context = val && val.to_sym + context = val && val.to_s super || context && begin - handler = handler_for_context - [true, handler, payload['text'].try!(:split) || []] if handler + args = payload['text'].try!(:split) || [] + action = action_for_message_context(context) + [[action, type: :message_context, context: context], args] end end # Save context for the next request. def save_context(context) message_context_session[:context] = context end - def handler_for_context - self.class.context_handlers[context] || self.class.context_to_action && begin - action_name = context.to_s - unless action_method?(action_name) - raise AbstractController::ActionNotFound, - "The action '#{action_name}' could not be set from context " \ - "for #{self.class.name}. " \ - 'context_to_action! supports only action methods for security reasons. ' \ - 'If you need to call this action use context_handler for it.' - end - action_name - end + # Returns action name for message context. By default it's the same as context name. + # Raises AbstractController::ActionNotFound if action is not available. + # This differs from other cases where invalid actions are silently ignored, + # because message context is controlled by developer, and users are not able + # to construct update to run any specific context. + def action_for_message_context(context) + action = context.to_s + return action if action_method?(action) + raise AbstractController::ActionNotFound, + "The context action '#{action}' is not found in #{self.class.name}" end end end end end