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

Contextual actions for callback_query

Этот коммит содержится в:
Max Melentiev
2016-05-17 10:51:45 +03:00
родитель 8994328654
Коммит 23fb9a28d1
5 изменённых файлов: 107 добавлений и 1 удалений

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

@@ -1,7 +1,7 @@
# 0.7.0 Unreleased
- New Bot API methods.
- Helpers for inline keyboards.
- Helpers for inline keyboards, support for callback_query (with contextual actions).
- Changed action methods signature
- `#inline_query(payload) -> #inline_query(query, offset)`
- `#chosen_inline_result(payload)` -> `#chosen_inline_result(result_id, query)`

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

@@ -236,6 +236,12 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
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:
```ruby

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

@@ -57,6 +57,7 @@ module Telegram
require 'telegram/bot/updates_controller/log_subscriber'
require 'telegram/bot/updates_controller/instrumentation'
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 :Botan, 'telegram/bot/updates_controller/botan'

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

@@ -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