зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-08-28 15:26:18 +03:00
Merge pull request #207 from telegram-bot-rb/webhook_request
Add UpdatesController#webhook_request
Этот коммит содержится в:
@@ -1,5 +1,7 @@
|
||||
# Unreleased
|
||||
|
||||
- Add `UpdatesController#webhook_request` that is set to `ActionDispatch::Request`
|
||||
in webhook mode.
|
||||
- Update to Bot API 6.8
|
||||
- Added `chat_join_request` to PAYLOAD_TYPES
|
||||
|
||||
|
||||
@@ -430,6 +430,10 @@ There are several options to run it automatically:
|
||||
- Use `Telegram::Bot::Middleware` with rack ([example in wiki](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application)).
|
||||
- Use poller (described in the next section).
|
||||
|
||||
When controller runs in webhook mode `Telegram::Bot::Middleware` passes
|
||||
`ActionDispatch::Request` object to the `.dispatch` method.
|
||||
It's available via `#webhook_request` controller method.
|
||||
|
||||
To run action without update (ex., send notifications from jobs),
|
||||
you can call `#process` directly. In this case controller can be initialized
|
||||
with `:from` and/or `:chat` options instead of `update` object:
|
||||
|
||||
@@ -16,7 +16,7 @@ module Telegram
|
||||
def call(env)
|
||||
request = ActionDispatch::Request.new(env)
|
||||
update = request.request_parameters
|
||||
controller.dispatch(bot, update)
|
||||
controller.dispatch(bot, update, request)
|
||||
[200, {}, ['']]
|
||||
end
|
||||
|
||||
|
||||
@@ -118,21 +118,24 @@ module Telegram
|
||||
end
|
||||
end
|
||||
|
||||
attr_internal_reader :update, :bot, :payload, :payload_type
|
||||
attr_internal_reader :bot, :payload, :payload_type, :update, :webhook_request
|
||||
delegate :username, to: :bot, prefix: true, allow_nil: true
|
||||
|
||||
# Second argument can be either update object with hash access & string
|
||||
# `update` can be either update object with hash access & string
|
||||
# keys or Hash with `:from` or `:chat` to override this values and assume
|
||||
# that update is nil.
|
||||
def initialize(bot = nil, update = nil)
|
||||
# ActionDispatch::Request object is passed in `webhook_request` when bot running
|
||||
# in webhook mode.
|
||||
def initialize(bot = nil, update = nil, webhook_request = nil)
|
||||
if update.is_a?(Hash) && (update.key?(:from) || update.key?(:chat))
|
||||
options = update
|
||||
update = nil
|
||||
end
|
||||
@_update = update
|
||||
@_bot = bot
|
||||
@_update = update
|
||||
@_chat, @_from = options && options.values_at(:chat, :from)
|
||||
@_payload, @_payload_type = self.class.payload_from_update(update)
|
||||
@_webhook_request = webhook_request
|
||||
end
|
||||
|
||||
# Accessor to `'chat'` field of payload. Also tries `'chat'` in `'message'`
|
||||
|
||||
@@ -13,8 +13,9 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
|
||||
x.extend Telegram::Bot::UpdatesController::Testing
|
||||
end
|
||||
end
|
||||
let(:controller_args) { [bot, deep_stringify(update)] }
|
||||
let(:controller_args) { [bot, deep_stringify(update), webhook_request] }
|
||||
let(:update) { {payload_type => payload} }
|
||||
let(:webhook_request) { nil }
|
||||
let(:payload_type) { :some_type }
|
||||
let(:payload) { double(:payload) }
|
||||
let(:bot) { Telegram::Bot::ClientStub.new(bot_name) }
|
||||
@@ -22,8 +23,8 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
|
||||
let(:session) { controller.send(:session) }
|
||||
|
||||
# Process update.
|
||||
def dispatch(update = self.update, bot = self.bot)
|
||||
controller.dispatch_again(bot, deep_stringify(update))
|
||||
def dispatch(update = self.update, bot = self.bot, webhook_request = self.webhook_request)
|
||||
controller.dispatch_again(bot, deep_stringify(update), webhook_request)
|
||||
end
|
||||
|
||||
# Same as `.as_json` but mocks-friendly.
|
||||
|
||||
@@ -5,9 +5,9 @@ module Telegram
|
||||
IVARS_TO_KEEP = %i[@_session].freeze
|
||||
|
||||
# Perform multiple dispatches on same instance.
|
||||
def dispatch_again(bot = nil, update = nil)
|
||||
def dispatch_again(bot = nil, update = nil, webhook_request = nil)
|
||||
recycle!
|
||||
initialize(bot, update)
|
||||
initialize(bot, update, webhook_request)
|
||||
dispatch
|
||||
end
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ module Telegram
|
||||
# Include this module to type cast update to Virtus model
|
||||
# using `telegram-bot-types` gem (install this gem first).
|
||||
module TypedUpdate
|
||||
def initialize(bot = nil, update = nil)
|
||||
def initialize(bot = nil, update = nil, webhook_request = nil)
|
||||
update = Types::Update.new(update) if update && !update.is_a?(Types::Update)
|
||||
super
|
||||
end
|
||||
|
||||
@@ -10,4 +10,13 @@ RSpec.describe DefaultBotController, telegram_bot: :rails do
|
||||
subject { -> { dispatch_command :load_session } }
|
||||
it { should_not raise_error }
|
||||
end
|
||||
|
||||
describe '#dispatch' do
|
||||
it 'provides webhook_request' do
|
||||
expect(described_class).to receive(:dispatch).
|
||||
with(bot, hash_including('message'), instance_of(ActionDispatch::Request)).
|
||||
and_call_original
|
||||
dispatch_message :test
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,8 @@ RSpec.describe Telegram::Bot::Middleware do
|
||||
end
|
||||
|
||||
it 'calls dispatch on controller' do
|
||||
expect(controller).to receive(:dispatch).with(bot, update)
|
||||
expect(controller).to receive(:dispatch).
|
||||
with(bot, update, instance_of(ActionDispatch::Request))
|
||||
subject
|
||||
end
|
||||
|
||||
|
||||
@@ -2,4 +2,13 @@ require 'telegram/bot/rspec/integration/poller'
|
||||
|
||||
RSpec.describe 'Poller integration spec', telegram_bot: :poller do
|
||||
include_examples 'shared integration examples'
|
||||
|
||||
describe '#dispatch' do
|
||||
it 'doesn`t provide webhook_request' do
|
||||
expect(controller_class).to receive(:dispatch).
|
||||
with(bot, hash_including('message')).
|
||||
and_call_original
|
||||
dispatch_message :test
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,4 +17,13 @@ RSpec.describe 'Rack integration spec', telegram_bot: :rack do
|
||||
ActionDispatch::ParamsParser.new(app)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#dispatch' do
|
||||
it 'provides webhook_request' do
|
||||
expect(controller_class).to receive(:dispatch).
|
||||
with(bot, hash_including('message'), instance_of(ActionDispatch::Request)).
|
||||
and_call_original
|
||||
dispatch_message :test
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'action_dispatch'
|
||||
|
||||
RSpec.describe Telegram::Bot::UpdatesController::Testing do
|
||||
include_context 'telegram/bot/updates_controller'
|
||||
let(:controller_class) do
|
||||
@@ -24,4 +26,27 @@ RSpec.describe Telegram::Bot::UpdatesController::Testing do
|
||||
it { should_not change { controller.send(:session)[:key] }.from 'sval' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#dispatch' do
|
||||
it 'doesn`t provide webhook_request' do
|
||||
dispatch
|
||||
expect(controller.webhook_request).to eq nil
|
||||
end
|
||||
|
||||
context 'when webhook_request is set' do
|
||||
let(:webhook_request) { ActionDispatch::Request.new({}) }
|
||||
it 'passes it to controller' do
|
||||
dispatch
|
||||
expect(controller.webhook_request).to eq webhook_request
|
||||
end
|
||||
end
|
||||
|
||||
context 'when webhook_request is given' do
|
||||
it 'passes it to controller' do
|
||||
webhook_request = ::ActionDispatch::Request.new({})
|
||||
dispatch(update, bot, webhook_request)
|
||||
expect(controller.webhook_request).to eq webhook_request
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Ссылка в новой задаче
Block a user