зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-09-07 11:25:52 +03:00
Use token hash in routes instead of plain value, support :path option
Этот коммит содержится в:
@@ -1,5 +1,9 @@
|
|||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
|
- Add `:path` option to `telegram_webhook` route helper.
|
||||||
|
- __Breaking change!__ Default route is generated using hashed bot token.
|
||||||
|
Please reconfigure webhook after update (`rake telegram:bot:set_webhook`).
|
||||||
|
|
||||||
# 0.14.4
|
# 0.14.4
|
||||||
|
|
||||||
- Update to Bot API 4.7
|
- Update to Bot API 4.7
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ end
|
|||||||
### Routes in Rails app
|
### Routes in Rails app
|
||||||
|
|
||||||
There is `telegram_webhook` helper for rails app to define routes for webhooks.
|
There is `telegram_webhook` helper for rails app to define routes for webhooks.
|
||||||
It defines routes at `telegram/#{bot.token}` and connects bots with controller.
|
It defines routes at `telegram/#{hash_of(bot.token)}` and connects bots with controller.
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# Most off apps would require
|
# Most off apps would require
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
require 'base64'
|
||||||
|
require 'openssl'
|
||||||
|
|
||||||
require 'telegram/bot'
|
require 'telegram/bot'
|
||||||
require 'active_support/core_ext/array/wrap'
|
require 'active_support/core_ext/array/wrap'
|
||||||
|
|
||||||
@@ -17,10 +20,8 @@ module Telegram
|
|||||||
end || 'telegram_webhook'
|
end || 'telegram_webhook'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Replaces colon with underscore so rails don't treat it as
|
def token_hash(token)
|
||||||
# route parameter.
|
Base64.urlsafe_encode64(OpenSSL::Digest::SHA1.digest(token), padding: false)
|
||||||
def escape_token(token)
|
|
||||||
token && token.tr(':', '_')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -34,14 +35,17 @@ module Telegram
|
|||||||
#
|
#
|
||||||
# # pass additional options
|
# # pass additional options
|
||||||
# telegram_webhook TelegramController, :default, as: :custom_route_name
|
# telegram_webhook TelegramController, :default, as: :custom_route_name
|
||||||
def telegram_webhook(controller, bot = :default, **options)
|
#
|
||||||
|
# # Default path is generated using hashed bot token. Override it using:
|
||||||
|
# telegram_webhook TelegramController, :default, path: 'top/secret'
|
||||||
|
def telegram_webhook(controller, bot = :default, path: nil, **options)
|
||||||
bot = Client.wrap(bot)
|
bot = Client.wrap(bot)
|
||||||
params = {
|
params = {
|
||||||
to: Middleware.new(bot, controller),
|
to: Middleware.new(bot, controller),
|
||||||
as: RoutesHelper.route_name_for_bot(bot),
|
as: RoutesHelper.route_name_for_bot(bot),
|
||||||
format: false,
|
format: false,
|
||||||
}.merge!(options)
|
}.merge!(options)
|
||||||
post("telegram/#{RoutesHelper.escape_token bot.token}", params)
|
post(path || "telegram/#{bot.token && RoutesHelper.token_hash(bot.token)}", params)
|
||||||
UpdatesPoller.add(bot, controller) if Telegram.bot_poller_mode?
|
UpdatesPoller.add(bot, controller) if Telegram.bot_poller_mode?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,57 +41,61 @@ RSpec.describe Telegram::Bot::RoutesHelper do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#telegram_webhook' do
|
describe '#telegram_webhook' do
|
||||||
subject { mapper.telegram_webhook(*input) }
|
subject { ->(*args) { mapper.telegram_webhook(*args) } }
|
||||||
let(:mapper) { double(:mapper).tap { |x| x.extend described_class } }
|
let(:mapper) { double(:mapper).tap { |x| x.extend described_class } }
|
||||||
let(:bots) { {default: bot, other: other_bot} }
|
|
||||||
let(:controller) { double(:controller, name: :controller) }
|
let(:controller) { double(:controller, name: :controller) }
|
||||||
let(:other_controller) { double(:other_controller, name: :other_controller) }
|
|
||||||
before { allow(Telegram).to receive(:bots) { bots } }
|
before { allow(Telegram).to receive(:bots) { bots } }
|
||||||
|
|
||||||
def assert_routes(bot, controller, route_name, options) # rubocop:disable AbcSize
|
def assert_route(bot, controller, path: nil, **expected_options) # rubocop:disable AbcSize
|
||||||
expected_path = options.delete(:path) || "telegram/#{bot.token}"
|
path ||= "telegram/#{described_class.token_hash(bot.token)}"
|
||||||
expect(mapper).to receive(:post) do |path, params|
|
expect(mapper).to receive(:post) do |actual_path, actual_options|
|
||||||
expect(path).to eq expected_path
|
expect(actual_path).to eq(path)
|
||||||
middleware = params[:to]
|
middleware = actual_options[:to]
|
||||||
expect(middleware.controller).to eq(controller)
|
expect(middleware.controller).to eq(controller)
|
||||||
expect(middleware.bot.token).to eq(bot.token)
|
expect(middleware.bot.token).to eq(bot.token)
|
||||||
expect(middleware.bot.username).to eq(bot.username)
|
expect(middleware.bot.username).to eq(bot.username)
|
||||||
expect(params[:as]).to eq route_name
|
expect(actual_options).to include(expected_options)
|
||||||
expect(params).to include(options) if options
|
|
||||||
end
|
end
|
||||||
subject
|
yield
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when called with controller' do
|
it 'creates routes for default bot' do
|
||||||
let(:input) { [controller, option: :val] }
|
assert_route(bot, controller, as: 'default_telegram_webhook') do
|
||||||
|
subject[controller]
|
||||||
it 'creates routes for default bot and this controller' do
|
|
||||||
assert_routes bot, controller, 'default_telegram_webhook', option: :val
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'and bot does not have configured token' do
|
other_controller = double(:other_controller, name: :other_controller)
|
||||||
let(:bot) { create_bot(nil) }
|
assert_route(bot, other_controller, as: 'custom_route') do
|
||||||
it 'creates routes for default bot and this controller' do
|
subject[other_controller, as: 'custom_route']
|
||||||
assert_routes bot, controller, 'default_telegram_webhook', option: :val
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'and bot has colon in token' do
|
it 'passes extra options' do
|
||||||
let(:bot) { create_bot('some:token') }
|
assert_route(bot, controller, as: 'default_telegram_webhook', option: :val, other: 2) do
|
||||||
it 'replaces colon with underscore' do
|
subject[controller, option: :val, other: 2]
|
||||||
assert_routes bot, controller, 'default_telegram_webhook',
|
end
|
||||||
option: :val,
|
end
|
||||||
path: 'telegram/some_token'
|
|
||||||
|
it 'uses :path param to override default path' do
|
||||||
|
assert_route(bot, controller, as: 'default_telegram_webhook', path: 'custom/path') do
|
||||||
|
subject[controller, path: 'custom/path']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when bot does not have configured token' do
|
||||||
|
let(:bot) { create_bot(nil) }
|
||||||
|
it 'creates route anyway' do
|
||||||
|
assert_route(bot, controller, as: 'default_telegram_webhook', path: 'telegram/') do
|
||||||
|
subject[controller]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when called with controller and smth castable to bot' do
|
context 'when called with controller and smth castable to bot' do
|
||||||
let(:input) { [controller, 'custom_token', option: :val] }
|
|
||||||
|
|
||||||
it 'creates routes for every created bot and controller' do
|
it 'creates routes for every created bot and controller' do
|
||||||
assert_routes create_bot('custom_token'), controller, 'telegram_webhook',
|
assert_route(create_bot('custom_token'), controller, as: 'telegram_webhook') do
|
||||||
option: :val
|
subject[controller, 'custom_token']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user