зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-09-08 03:45:52 +03:00
Contextual actions for callback_query
Этот коммит содержится в:
@@ -1,7 +1,7 @@
|
|||||||
# 0.7.0 Unreleased
|
# 0.7.0 Unreleased
|
||||||
|
|
||||||
- New Bot API methods.
|
- New Bot API methods.
|
||||||
- Helpers for inline keyboards.
|
- Helpers for inline keyboards, support for callback_query (with contextual actions).
|
||||||
- Changed action methods signature
|
- Changed action methods signature
|
||||||
- `#inline_query(payload) -> #inline_query(query, offset)`
|
- `#inline_query(payload) -> #inline_query(query, offset)`
|
||||||
- `#chosen_inline_result(payload)` -> `#chosen_inline_result(result_id, query)`
|
- `#chosen_inline_result(payload)` -> `#chosen_inline_result(result_id, query)`
|
||||||
|
|||||||
@@ -236,6 +236,12 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can use `CallbackQueyContext` in the similar way to split `#callback_query` into
|
||||||
|
several specific methods. It doesn't require session support, and takes context from
|
||||||
|
data. If data has a prefix with colon like this `my_ctx:smth...` it'll call
|
||||||
|
`my_ctx_callback_query('smth...')` when there is such action method. Otherwise
|
||||||
|
it'll call `callback_query('my_ctx:smth...')` as usual.
|
||||||
|
|
||||||
To process update run:
|
To process update run:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ module Telegram
|
|||||||
require 'telegram/bot/updates_controller/log_subscriber'
|
require 'telegram/bot/updates_controller/log_subscriber'
|
||||||
require 'telegram/bot/updates_controller/instrumentation'
|
require 'telegram/bot/updates_controller/instrumentation'
|
||||||
require 'telegram/bot/updates_controller/reply_helpers'
|
require 'telegram/bot/updates_controller/reply_helpers'
|
||||||
|
autoload :CallbackQueyContext, 'telegram/bot/updates_controller/callback_query_context'
|
||||||
autoload :MessageContext, 'telegram/bot/updates_controller/message_context'
|
autoload :MessageContext, 'telegram/bot/updates_controller/message_context'
|
||||||
autoload :Botan, 'telegram/bot/updates_controller/botan'
|
autoload :Botan, 'telegram/bot/updates_controller/botan'
|
||||||
|
|
||||||
|
|||||||
34
lib/telegram/bot/updates_controller/callback_query_context.rb
Обычный файл
34
lib/telegram/bot/updates_controller/callback_query_context.rb
Обычный файл
@@ -0,0 +1,34 @@
|
|||||||
|
module Telegram
|
||||||
|
module Bot
|
||||||
|
class UpdatesController
|
||||||
|
# Use separate actions for different callback queries.
|
||||||
|
# It doesn't require session support. Simply add `%{context}:` prefix to data.
|
||||||
|
module CallbackQueyContext
|
||||||
|
protected
|
||||||
|
|
||||||
|
# Uses #context_from_callback_query as context name.
|
||||||
|
# If context is present checks if `%context%_callback_query` is valid
|
||||||
|
# action method and returns it if so. Context is stripped from data
|
||||||
|
# in this case. Otherwise returns `super`.
|
||||||
|
#
|
||||||
|
# It wont raise ActionNotFound as MessageContext does,
|
||||||
|
# because `data` param is controlled by client.
|
||||||
|
def action_for_callback_query
|
||||||
|
context, new_data = context_from_callback_query
|
||||||
|
# binding.pry
|
||||||
|
if context
|
||||||
|
action_name = "#{context}_callback_query"
|
||||||
|
[false, action_name, [new_data]] if action_method?(action_name)
|
||||||
|
end || super
|
||||||
|
end
|
||||||
|
|
||||||
|
def context_from_callback_query
|
||||||
|
data = payload['data']
|
||||||
|
return unless data
|
||||||
|
parts = data.split(':', 2)
|
||||||
|
parts if parts.size > 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
RSpec.describe Telegram::Bot::UpdatesController::CallbackQueyContext do
|
||||||
|
include_context 'telegram/bot/updates_controller'
|
||||||
|
let(:controller_class) do
|
||||||
|
described_class = self.described_class
|
||||||
|
Class.new(Telegram::Bot::UpdatesController) do
|
||||||
|
include described_class
|
||||||
|
|
||||||
|
attr_accessor :filter_done
|
||||||
|
before_action only: :ctx2_callback_query do
|
||||||
|
self.filter_done = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def callback_query(data)
|
||||||
|
[:no_context, data]
|
||||||
|
end
|
||||||
|
|
||||||
|
def ctx1_callback_query(data)
|
||||||
|
[:ctx1, data]
|
||||||
|
end
|
||||||
|
|
||||||
|
def ctx2_callback_query(data)
|
||||||
|
[:ctx2, data]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#dispatch' do
|
||||||
|
subject { -> { dispatch } }
|
||||||
|
let(:payload_type) { :callback_query }
|
||||||
|
let(:payload) { {'data' => data} }
|
||||||
|
let(:data) { text }
|
||||||
|
let(:text) { 'asd qwe zxc' }
|
||||||
|
|
||||||
|
context 'when context is not set' do
|
||||||
|
its(:call) { should eq [:no_context, text] }
|
||||||
|
it { should_not change(controller, :filter_done) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when context is set' do
|
||||||
|
let(:data) { "#{ctx}:#{text}" }
|
||||||
|
|
||||||
|
context 'and valid' do
|
||||||
|
let(:ctx) { 'ctx1' }
|
||||||
|
its(:call) { should eq [:ctx1, text] }
|
||||||
|
it { should_not change(controller, :filter_done) }
|
||||||
|
|
||||||
|
context 'and context has callback' do
|
||||||
|
let(:ctx) { 'ctx2' }
|
||||||
|
its(:call) { should eq [:ctx2, text] }
|
||||||
|
it { should change(controller, :filter_done) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and data has multiple colons' do
|
||||||
|
let(:text) { super().tr(' ', ':') }
|
||||||
|
its(:call) { should eq [:ctx1, text] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and invalid' do
|
||||||
|
let(:ctx) { 'missing' }
|
||||||
|
its(:call) { should eq [:no_context, data] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Ссылка в новой задаче
Block a user