1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-09-07 19:35:52 +03:00

MessageContext doesnt use #process to run actions

Этот коммит содержится в:
Max Melentiev
2016-05-12 00:28:22 +03:00
родитель 9b3fb562a3
Коммит 1f139a2b36
4 изменённых файлов: 46 добавлений и 35 удалений

Просмотреть файл

@@ -200,8 +200,8 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
end end
# register context handlers to handle this context # register context handlers to handle this context
context_handler :rename do |message| context_handler :rename do |*words|
update_name message[:text] update_name words[0]
reply_with :message, text: 'Renamed!' reply_with :message, text: 'Renamed!'
end end

Просмотреть файл

@@ -159,13 +159,16 @@ module Telegram
# Returns array `[is_command?, action, args]`. # Returns array `[is_command?, action, args]`.
def action_for_payload def action_for_payload
case payload_type case payload_type
when 'message' when 'message' then action_for_message
cmd, args = self.class.command_from_text(payload['text'], bot_username)
cmd &&= self.class.action_for_command(cmd)
[true, cmd, args] if cmd
end || [false, payload_type, [payload]] end || [false, payload_type, [payload]]
end end
def action_for_message
cmd, args = self.class.command_from_text(payload['text'], bot_username)
cmd &&= self.class.action_for_command(cmd)
[true, cmd, args] if cmd
end
# Silently ignore unsupported messages. # Silently ignore unsupported messages.
# Params are `action, *args`. # Params are `action, *args`.
def action_missing(*) def action_missing(*)

Просмотреть файл

@@ -10,7 +10,6 @@ module Telegram
included do included do
# As we use before_action context is cleared anyway, # As we use before_action context is cleared anyway,
# no matter we used it or not. # no matter we used it or not.
before_action :fetch_context
singleton_class.send :attr_reader, :context_handlers, :context_to_action singleton_class.send :attr_reader, :context_handlers, :context_to_action
@context_handlers = {} @context_handlers = {}
end end
@@ -18,26 +17,26 @@ module Telegram
module ClassMethods module ClassMethods
# Registers handler for context. # Registers handler for context.
# #
# context_handler :rename do |message| # context_handler :rename do |*|
# resource.update!(name: message['text']) # resource.update!(name: payload['text'])
# end # end
# #
# # To run other action with all the callbacks: # # To run other action with all the callbacks:
# context_handler :rename do |message| # context_handler :rename do |*words|
# process(:rename, *m['text'].try!(:split)) # Message can be without text # process(:rename, *words)
# end # end
# #
# # Or just # # Or just
# context_handler :rename, :your_action_to_call # context_handler :rename, :your_action_to_call
# context_handler :rename # to call :rename # context_handler :rename # to call :rename
# #
# # For messages without context use this instead of `message` method:
# context_handler do |message|
# end
#
def context_handler(context = nil, action = nil, &block) def context_handler(context = nil, action = nil, &block)
context &&= context.to_sym context &&= context.to_sym
context_handlers[context] = block || action || context if block
action = "_context_handler_#{context}"
define_method(action, &block)
end
context_handlers[context] = action || context
end end
# Use it to use context value as action name for all contexts # Use it to use context value as action name for all contexts
@@ -49,20 +48,9 @@ module Telegram
end end
end end
# Finds handler for current context and processes message with it.
def message(message)
handler = handler_for_context
return unless handler
if handler.respond_to?(:call)
instance_exec(message, &handler)
else
process(handler, *message['text'].try!(:split))
end
end
# Action to clear context. # Action to clear context.
def cancel def cancel
# Context is already cleared in before_action # Context is already cleared in action_for_message
end end
private private
@@ -71,11 +59,15 @@ module Telegram
# according to previous request. # according to previous request.
attr_reader :context attr_reader :context
# Fetches and removes context from session. # Fetches context and finds handler for it. If message has new command,
def fetch_context # it has higher priority than contextual action.
def action_for_message
val = session.delete(:context) val = session.delete(:context)
@context = val && val.to_sym @context = val && val.to_sym
true # TODO: remove in Rails 5.0 super || context && begin
handler = handler_for_context
[true, handler, payload['text'].try!(:split) || []] if handler
end
end end
# Save context for the next request. # Save context for the next request.

Просмотреть файл

@@ -10,7 +10,10 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
self.filter_done = true self.filter_done = true
end end
context_handler do |*args| attr_reader :callbacks_runs
before_action { @callbacks_runs = (@callbacks_runs || 0) + 1 }
def message(*args)
[:no_context, *args] [:no_context, *args]
end end
@@ -51,13 +54,19 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
context 'when context is handled by block' do context 'when context is handled by block' do
before { session[:context] = :block } before { session[:context] = :block }
its(:call) { should eq [:block_result, payload] } its(:call) { should eq [:block_result, *text.split] }
it { should_not change(controller, :filter_done) } it { should_not change(controller, :filter_done) }
it { should change { session[:context] }.to nil } it { should change { session[:context] }.to nil }
context 'when message has no text' do context 'when message has no text' do
let(:payload) { {'audio' => {'file_id' => 123}} } let(:payload) { {'audio' => {'file_id' => 123}} }
its(:call) { should eq [:block_result, payload] } its(:call) { should eq [:block_result] }
end
context 'when message has new command' do
let(:text) { '/action a s d' }
its(:call) { should eq [:action_result, *%w(a s d)] }
it { should change { session[:context] }.to nil }
end end
end end
@@ -66,6 +75,7 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
its(:call) { should eq [:method_result, *text.split] } its(:call) { should eq [:method_result, *text.split] }
it { should change(controller, :filter_done).to true } it { should change(controller, :filter_done).to true }
it { should change { session[:context] }.to nil } it { should change { session[:context] }.to nil }
it { should change(controller, :callbacks_runs).to 1 }
context 'when message has no text' do context 'when message has no text' do
let(:payload) { {'audio' => {'file_id' => 123}} } let(:payload) { {'audio' => {'file_id' => 123}} }
@@ -84,7 +94,7 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
context 'when context is action`s name but not mapped' do context 'when context is action`s name but not mapped' do
before { session[:context] = :action } before { session[:context] = :action }
its(:call) { should eq nil } its(:call) { should eq [:no_context, payload] }
it { should_not change(controller, :filter_done) } it { should_not change(controller, :filter_done) }
it { should change { session[:context] }.to nil } it { should change { session[:context] }.to nil }
end end
@@ -92,6 +102,12 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
context 'when context_to_action is true' do context 'when context_to_action is true' do
before { controller_class.context_to_action! } before { controller_class.context_to_action! }
context 'when context is not set' do
its(:call) { should eq [:no_context, payload] }
it { should_not change(controller, :filter_done) }
it { should_not change { session[:context] } }
end
context 'when context is action`s name but not mapped' do context 'when context is action`s name but not mapped' do
before { session[:context] = :action } before { session[:context] = :action }
its(:call) { should eq [:action_result, *text.split] } its(:call) { should eq [:action_result, *text.split] }