зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-09-07 19:35:52 +03:00
MessageContext doesnt use #process to run actions
Этот коммит содержится в:
@@ -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,11 +159,14 @@ 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
|
||||||
|
end || [false, payload_type, [payload]]
|
||||||
|
end
|
||||||
|
|
||||||
|
def action_for_message
|
||||||
cmd, args = self.class.command_from_text(payload['text'], bot_username)
|
cmd, args = self.class.command_from_text(payload['text'], bot_username)
|
||||||
cmd &&= self.class.action_for_command(cmd)
|
cmd &&= self.class.action_for_command(cmd)
|
||||||
[true, cmd, args] if cmd
|
[true, cmd, args] if cmd
|
||||||
end || [false, payload_type, [payload]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Silently ignore unsupported messages.
|
# Silently ignore unsupported messages.
|
||||||
|
|||||||
@@ -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] }
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user