зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-08-28 15:26:18 +03:00
Сравнить коммиты
36 Коммитов
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
544d392346 | ||
|
|
d048f42c6c | ||
|
|
f54b36d9b7 | ||
|
|
cd2d3d8d87 | ||
|
|
ee666f0e90 | ||
|
|
759b125d82 | ||
|
|
21ca16f613 | ||
|
|
7cfceb7439 | ||
|
|
29603e5b60 | ||
|
|
5822eff988 | ||
|
|
cbe7186c44 | ||
|
|
ca20bb0533 | ||
|
|
6f8565fbd5 | ||
|
|
a16928267a | ||
|
|
83bc13bac6 | ||
|
|
1e1814a26d | ||
|
|
ae9a6a501d | ||
|
|
74c2c28ab5 | ||
|
|
af85966939 | ||
|
|
5145c31d73 | ||
|
|
cbb3a85757 | ||
|
|
f0c5222c8f | ||
|
|
b4e5b056e0 | ||
|
|
be74094c90 | ||
|
|
e53c31b79f | ||
|
|
b40e4b432d | ||
|
|
ef5ec81386 | ||
|
|
7d8a19d3c8 | ||
|
|
380f6686fc | ||
|
|
ea64230eab | ||
|
|
5b9706ed47 | ||
|
|
2d73d1c879 | ||
|
|
88af1152cf | ||
|
|
586217585a | ||
|
|
f83bf92601 | ||
|
|
3049ced903 |
43
.github/workflows/ci.yml
поставляемый
Обычный файл
43
.github/workflows/ci.yml
поставляемый
Обычный файл
@@ -0,0 +1,43 @@
|
||||
name: Lint & Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
# lint:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: ruby/setup-ruby@v1
|
||||
# with:
|
||||
# ruby-version: '3.0'
|
||||
# bundler-cache: true
|
||||
# - run: bundle exec rubocop
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
ruby:
|
||||
- '2.7'
|
||||
gemfile:
|
||||
- gemfiles/rails_61.gemfile
|
||||
- gemfiles/rails_60.gemfile
|
||||
- gemfiles/rails_52.gemfile
|
||||
- gemfiles/rails_51.gemfile
|
||||
include:
|
||||
# ruby 3.x
|
||||
- ruby: '3.2'
|
||||
gemfile: gemfiles/rails_71.gemfile
|
||||
- ruby: '3.0'
|
||||
gemfile: gemfiles/rails_61.gemfile
|
||||
- ruby: '3.0'
|
||||
gemfile: gemfiles/rails_60.gemfile
|
||||
env:
|
||||
BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
bundler-cache: true
|
||||
- run: bundle exec rake spec
|
||||
30
.travis.yml
30
.travis.yml
@@ -1,30 +0,0 @@
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: ruby
|
||||
cache: bundler
|
||||
rvm:
|
||||
- 2.6
|
||||
- 2.5
|
||||
gemfile:
|
||||
- gemfiles/rails_61.gemfile
|
||||
- gemfiles/rails_60.gemfile
|
||||
- gemfiles/rails_52.gemfile
|
||||
jobs:
|
||||
include:
|
||||
# ruby 3.x
|
||||
- rvm: 3.0
|
||||
gemfile: gemfiles/rails_61.gemfile
|
||||
- rvm: 3.0
|
||||
gemfile: gemfiles/rails_60.gemfile
|
||||
# old rails
|
||||
- rvm: 2.5
|
||||
gemfile: gemfiles/rails_51.gemfile
|
||||
- rvm: 2.5
|
||||
gemfile: gemfiles/rails_50.gemfile
|
||||
- rvm: 2.5
|
||||
gemfile: gemfiles/rails_42.gemfile
|
||||
# old rubies
|
||||
- rvm: 2.4
|
||||
gemfile: gemfiles/rails_52.gemfile
|
||||
notifications:
|
||||
email: false
|
||||
20
Appraisals
20
Appraisals
@@ -1,3 +1,13 @@
|
||||
appraise 'rails-71' do
|
||||
gem 'actionpack', '~> 7.1.0'
|
||||
gem 'railties', '~> 7.1.0'
|
||||
end
|
||||
|
||||
appraise 'rails-70' do
|
||||
gem 'actionpack', '~> 7.0.0'
|
||||
gem 'railties', '~> 7.0.0'
|
||||
end
|
||||
|
||||
appraise 'rails-61' do
|
||||
gem 'actionpack', '~> 6.1.0'
|
||||
gem 'railties', '~> 6.1.0'
|
||||
@@ -17,13 +27,3 @@ appraise 'rails-51' do
|
||||
gem 'actionpack', '~> 5.1.0'
|
||||
gem 'railties', '~> 5.1.0'
|
||||
end
|
||||
|
||||
appraise 'rails-50' do
|
||||
gem 'actionpack', '~> 5.0.0'
|
||||
gem 'railties', '~> 5.0.0'
|
||||
end
|
||||
|
||||
appraise 'rails-42' do
|
||||
gem 'actionpack', '~> 4.2.0'
|
||||
gem 'railties', '~> 4.2.0'
|
||||
end
|
||||
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,5 +1,26 @@
|
||||
# Unreleased
|
||||
|
||||
# 0.16.1
|
||||
|
||||
- Fix logger in poller mode in rails 7.1
|
||||
|
||||
# 0.16.0
|
||||
|
||||
- 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
|
||||
|
||||
# 0.15.7
|
||||
|
||||
- Add support for editMessageMedia similar to sendMediaGroup.
|
||||
|
||||
# 0.15.6
|
||||
|
||||
- Rails 7.0 support.
|
||||
- Fix sending File objects in nested objects in sendMediaGroup.
|
||||
- Update to Bot API 5.7
|
||||
|
||||
# 0.15.4
|
||||
|
||||
- Update to Bot API 5.3
|
||||
|
||||
6
Gemfile
6
Gemfile
@@ -4,13 +4,13 @@ gemspec
|
||||
group :development do
|
||||
gem 'appraisal', '~> 2.2'
|
||||
|
||||
gem 'pry', '~> 0.13.1'
|
||||
gem 'pry-byebug', '~> 3.9.0'
|
||||
gem 'pry', '~> 0.14.1'
|
||||
gem 'pry-byebug', '~> 3.10.1'
|
||||
gem 'sdoc', '~> 2.0.3'
|
||||
|
||||
gem 'telegram-bot-types', '~> 0.6.3'
|
||||
|
||||
gem 'rspec', '~> 3.10.0'
|
||||
gem 'rspec', '~> 3.12.0'
|
||||
gem 'rspec-its', '~> 1.3.0'
|
||||
gem 'rspec-rails', '~> 4.0.2'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](http://badge.fury.io/rb/telegram-bot)
|
||||
[](https://codeclimate.com/github/telegram-bot-rb/telegram-bot)
|
||||
[](https://travis-ci.com/telegram-bot-rb/telegram-bot)
|
||||
[](https://github.com/telegram-bot-rb/telegram-bot/actions/workflows/ci.yml)
|
||||
|
||||
Tools for developing Telegram bots. Best used with Rails, but can be used in
|
||||
[standalone app](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application).
|
||||
@@ -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:
|
||||
@@ -539,7 +543,7 @@ end
|
||||
|
||||
There is a context for testing bot controller in the way similar to Rails controller tests.
|
||||
It's supposed to be a low-level alternative for integration tests. Among the differences is
|
||||
that controller tests use a single controller instance for all dispatches in specific exaple,
|
||||
that controller tests use a single controller instance for all dispatches in specific example,
|
||||
session is stubbed (does not use configured store engine), and update is not serialized
|
||||
so it also supports mocks. This can be useful for unit testing, but should not be used as
|
||||
the default way to test the bot.
|
||||
|
||||
@@ -7,11 +7,11 @@ gem "railties", "~> 5.1.0"
|
||||
|
||||
group :development do
|
||||
gem "appraisal", "~> 2.2"
|
||||
gem "pry", "~> 0.13.1"
|
||||
gem "pry-byebug", "~> 3.9.0"
|
||||
gem "pry", "~> 0.14.1"
|
||||
gem "pry-byebug", "~> 3.10.1"
|
||||
gem "sdoc", "~> 2.0.3"
|
||||
gem "telegram-bot-types", "~> 0.6.2"
|
||||
gem "rspec", "~> 3.10.0"
|
||||
gem "telegram-bot-types", "~> 0.6.3"
|
||||
gem "rspec", "~> 3.12.0"
|
||||
gem "rspec-its", "~> 1.3.0"
|
||||
gem "rspec-rails", "~> 4.0.2"
|
||||
gem "rubocop", "~> 0.52.1"
|
||||
|
||||
@@ -7,11 +7,11 @@ gem "railties", "~> 5.2.0"
|
||||
|
||||
group :development do
|
||||
gem "appraisal", "~> 2.2"
|
||||
gem "pry", "~> 0.13.1"
|
||||
gem "pry-byebug", "~> 3.9.0"
|
||||
gem "pry", "~> 0.14.1"
|
||||
gem "pry-byebug", "~> 3.10.1"
|
||||
gem "sdoc", "~> 2.0.3"
|
||||
gem "telegram-bot-types", "~> 0.6.2"
|
||||
gem "rspec", "~> 3.10.0"
|
||||
gem "telegram-bot-types", "~> 0.6.3"
|
||||
gem "rspec", "~> 3.12.0"
|
||||
gem "rspec-its", "~> 1.3.0"
|
||||
gem "rspec-rails", "~> 4.0.2"
|
||||
gem "rubocop", "~> 0.52.1"
|
||||
|
||||
@@ -7,11 +7,11 @@ gem "railties", "~> 6.0.0"
|
||||
|
||||
group :development do
|
||||
gem "appraisal", "~> 2.2"
|
||||
gem "pry", "~> 0.13.1"
|
||||
gem "pry-byebug", "~> 3.9.0"
|
||||
gem "pry", "~> 0.14.1"
|
||||
gem "pry-byebug", "~> 3.10.1"
|
||||
gem "sdoc", "~> 2.0.3"
|
||||
gem "telegram-bot-types", "~> 0.6.2"
|
||||
gem "rspec", "~> 3.10.0"
|
||||
gem "telegram-bot-types", "~> 0.6.3"
|
||||
gem "rspec", "~> 3.12.0"
|
||||
gem "rspec-its", "~> 1.3.0"
|
||||
gem "rspec-rails", "~> 4.0.2"
|
||||
gem "rubocop", "~> 0.52.1"
|
||||
|
||||
@@ -7,11 +7,11 @@ gem "railties", "~> 6.1.0"
|
||||
|
||||
group :development do
|
||||
gem "appraisal", "~> 2.2"
|
||||
gem "pry", "~> 0.13.1"
|
||||
gem "pry-byebug", "~> 3.9.0"
|
||||
gem "pry", "~> 0.14.1"
|
||||
gem "pry-byebug", "~> 3.10.1"
|
||||
gem "sdoc", "~> 2.0.3"
|
||||
gem "telegram-bot-types", "~> 0.6.2"
|
||||
gem "rspec", "~> 3.10.0"
|
||||
gem "telegram-bot-types", "~> 0.6.3"
|
||||
gem "rspec", "~> 3.12.0"
|
||||
gem "rspec-its", "~> 1.3.0"
|
||||
gem "rspec-rails", "~> 4.0.2"
|
||||
gem "rubocop", "~> 0.52.1"
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "actionpack", "~> 4.2.0"
|
||||
gem "railties", "~> 4.2.0"
|
||||
gem "actionpack", "~> 7.0.0"
|
||||
gem "railties", "~> 7.0.0"
|
||||
|
||||
group :development do
|
||||
gem "appraisal", "~> 2.2"
|
||||
gem "pry", "~> 0.13.1"
|
||||
gem "pry-byebug", "~> 3.9.0"
|
||||
gem "pry", "~> 0.14.1"
|
||||
gem "pry-byebug", "~> 3.10.1"
|
||||
gem "sdoc", "~> 2.0.3"
|
||||
gem "telegram-bot-types", "~> 0.6.2"
|
||||
gem "rspec", "~> 3.10.0"
|
||||
gem "telegram-bot-types", "~> 0.6.3"
|
||||
gem "rspec", "~> 3.12.0"
|
||||
gem "rspec-its", "~> 1.3.0"
|
||||
gem "rspec-rails", "~> 4.0.2"
|
||||
gem "rubocop", "~> 0.52.1"
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "actionpack", "~> 5.0.0"
|
||||
gem "railties", "~> 5.0.0"
|
||||
gem "actionpack", "~> 7.1.0"
|
||||
gem "railties", "~> 7.1.0"
|
||||
|
||||
group :development do
|
||||
gem "appraisal", "~> 2.2"
|
||||
gem "pry", "~> 0.13.1"
|
||||
gem "pry-byebug", "~> 3.9.0"
|
||||
gem "pry", "~> 0.14.1"
|
||||
gem "pry-byebug", "~> 3.10.1"
|
||||
gem "sdoc", "~> 2.0.3"
|
||||
gem "telegram-bot-types", "~> 0.6.2"
|
||||
gem "rspec", "~> 3.10.0"
|
||||
gem "telegram-bot-types", "~> 0.6.3"
|
||||
gem "rspec", "~> 3.12.0"
|
||||
gem "rspec-its", "~> 1.3.0"
|
||||
gem "rspec-rails", "~> 4.0.2"
|
||||
gem "rubocop", "~> 0.52.1"
|
||||
@@ -7,7 +7,11 @@ namespace :telegram do
|
||||
Rake::Task['environment'].invoke
|
||||
if ENV.fetch('LOG_TO_STDOUT') { Rails.env.development? }.present?
|
||||
console = ActiveSupport::Logger.new(STDERR)
|
||||
Rails.logger.extend ActiveSupport::Logger.broadcast console
|
||||
if ::Rails.logger.respond_to?(:broadcast_to)
|
||||
::Rails.logger.broadcast_to(console)
|
||||
else
|
||||
Rails.logger.extend ActiveSupport::Logger.broadcast console
|
||||
end
|
||||
end
|
||||
Telegram::Bot::UpdatesPoller.start(ENV['BOT'].try!(:to_sym) || :default)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
require 'active_support/core_ext/hash/keys'
|
||||
require 'json'
|
||||
require 'httpclient'
|
||||
|
||||
module Telegram
|
||||
@@ -8,7 +7,9 @@ module Telegram
|
||||
SERVER = 'https://api.telegram.org'.freeze
|
||||
URL_TEMPLATE = '%<server>s/bot%<token>s/'.freeze
|
||||
|
||||
autoload :RequestBodyFormatter, 'telegram/bot/client/request_body_formatter'
|
||||
autoload :TypedResponse, 'telegram/bot/client/typed_response'
|
||||
|
||||
prepend Async
|
||||
include DebugClient
|
||||
|
||||
@@ -35,16 +36,8 @@ module Telegram
|
||||
prepend TypedResponse
|
||||
end
|
||||
|
||||
# Encodes nested hashes as json.
|
||||
def prepare_body(body)
|
||||
body = body.dup
|
||||
body.each do |k, val|
|
||||
body[k] = val.to_json if val.is_a?(Hash) || val.is_a?(Array)
|
||||
end
|
||||
end
|
||||
|
||||
def prepare_async_args(action, body = {})
|
||||
[action.to_s, Async.prepare_hash(prepare_body(body))]
|
||||
[action.to_s, Async.prepare_hash(RequestBodyFormatter.format(body, action))]
|
||||
end
|
||||
|
||||
def error_for_response(response)
|
||||
@@ -70,7 +63,7 @@ module Telegram
|
||||
end
|
||||
|
||||
def request(action, body = {})
|
||||
response = http_request("#{base_uri}#{action}", self.class.prepare_body(body))
|
||||
response = http_request("#{base_uri}#{action}", RequestBodyFormatter.format(body, action))
|
||||
raise self.class.error_for_response(response) if response.status >= 300
|
||||
JSON.parse(response.body)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Generated with bin/fetch-telegram-methods
|
||||
# Bot API 5.3
|
||||
# Bot API 6.8
|
||||
|
||||
getUpdates
|
||||
setWebhook
|
||||
@@ -21,8 +21,6 @@ sendVoice
|
||||
sendVideoNote
|
||||
sendMediaGroup
|
||||
sendLocation
|
||||
editMessageLiveLocation
|
||||
stopMessageLiveLocation
|
||||
sendVenue
|
||||
sendContact
|
||||
sendPoll
|
||||
@@ -35,11 +33,15 @@ unbanChatMember
|
||||
restrictChatMember
|
||||
promoteChatMember
|
||||
setChatAdministratorCustomTitle
|
||||
banChatSenderChat
|
||||
unbanChatSenderChat
|
||||
setChatPermissions
|
||||
exportChatInviteLink
|
||||
createChatInviteLink
|
||||
editChatInviteLink
|
||||
revokeChatInviteLink
|
||||
approveChatJoinRequest
|
||||
declineChatJoinRequest
|
||||
setChatPhoto
|
||||
deleteChatPhoto
|
||||
setChatTitle
|
||||
@@ -54,30 +56,64 @@ getChatMemberCount
|
||||
getChatMember
|
||||
setChatStickerSet
|
||||
deleteChatStickerSet
|
||||
getForumTopicIconStickers
|
||||
createForumTopic
|
||||
editForumTopic
|
||||
closeForumTopic
|
||||
reopenForumTopic
|
||||
deleteForumTopic
|
||||
unpinAllForumTopicMessages
|
||||
editGeneralForumTopic
|
||||
closeGeneralForumTopic
|
||||
reopenGeneralForumTopic
|
||||
hideGeneralForumTopic
|
||||
unhideGeneralForumTopic
|
||||
unpinAllGeneralForumTopicMessages
|
||||
answerCallbackQuery
|
||||
setMyCommands
|
||||
deleteMyCommands
|
||||
getMyCommands
|
||||
setMyName
|
||||
getMyName
|
||||
setMyDescription
|
||||
getMyDescription
|
||||
setMyShortDescription
|
||||
getMyShortDescription
|
||||
setChatMenuButton
|
||||
getChatMenuButton
|
||||
setMyDefaultAdministratorRights
|
||||
getMyDefaultAdministratorRights
|
||||
|
||||
editMessageText
|
||||
editMessageCaption
|
||||
editMessageMedia
|
||||
editMessageLiveLocation
|
||||
stopMessageLiveLocation
|
||||
editMessageReplyMarkup
|
||||
stopPoll
|
||||
deleteMessage
|
||||
|
||||
sendSticker
|
||||
getStickerSet
|
||||
getCustomEmojiStickers
|
||||
uploadStickerFile
|
||||
createNewStickerSet
|
||||
addStickerToSet
|
||||
setStickerPositionInSet
|
||||
deleteStickerFromSet
|
||||
setStickerSetThumb
|
||||
setStickerEmojiList
|
||||
setStickerKeywords
|
||||
setStickerMaskPosition
|
||||
setStickerSetTitle
|
||||
setStickerSetThumbnail
|
||||
setCustomEmojiStickerSetThumbnail
|
||||
deleteStickerSet
|
||||
|
||||
answerInlineQuery
|
||||
answerWebAppQuery
|
||||
|
||||
sendInvoice
|
||||
createInvoiceLink
|
||||
answerShippingQuery
|
||||
answerPreCheckoutQuery
|
||||
|
||||
|
||||
61
lib/telegram/bot/client/request_body_formatter.rb
Обычный файл
61
lib/telegram/bot/client/request_body_formatter.rb
Обычный файл
@@ -0,0 +1,61 @@
|
||||
require 'json'
|
||||
|
||||
module Telegram
|
||||
module Bot
|
||||
class Client
|
||||
# Encodes nested hashes and arrays as json and extract File objects from them
|
||||
# to the top level. Top-level File objects are handled by httpclient.
|
||||
# More details: https://core.telegram.org/bots/api#sending-files
|
||||
module RequestBodyFormatter
|
||||
extend self
|
||||
|
||||
def format(body, action)
|
||||
body = body.dup
|
||||
case action.to_s
|
||||
when 'sendMediaGroup'
|
||||
extract_files_from_array!(body, :media)
|
||||
when 'editMessageMedia'
|
||||
replace_field(body, :media) do |value|
|
||||
files = {}
|
||||
extract_files_from_hash(value, files).tap { body.merge!(files) }
|
||||
end
|
||||
end
|
||||
body.each do |key, val|
|
||||
body[key] = val.to_json if val.is_a?(Hash) || val.is_a?(Array)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Detects field by symbol or string name and replaces it with mapped value.
|
||||
def replace_field(hash, field_name)
|
||||
field_name = [field_name.to_sym, field_name.to_s].find { |x| hash.key?(x) }
|
||||
hash[field_name] = yield hash[field_name] if field_name
|
||||
end
|
||||
|
||||
def extract_files_from_array!(hash, field_name)
|
||||
replace_field(hash, field_name) do |value|
|
||||
break value unless value.is_a?(Array)
|
||||
files = {}
|
||||
value.map { |x| extract_files_from_hash(x, files) }.
|
||||
tap { hash.merge!(files) }
|
||||
end
|
||||
end
|
||||
|
||||
# Replace File objects with `attach` URIs. File objects are added into `files` hash.
|
||||
def extract_files_from_hash(hash, files)
|
||||
return hash unless hash.is_a?(Hash)
|
||||
hash.transform_values do |value|
|
||||
if value.is_a?(File)
|
||||
arg_name = "_file#{files.size}"
|
||||
files[arg_name] = value
|
||||
"attach://#{arg_name}"
|
||||
else
|
||||
value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ module Telegram
|
||||
poll_answer
|
||||
my_chat_member
|
||||
chat_member
|
||||
chat_join_request
|
||||
].freeze
|
||||
|
||||
class << self
|
||||
@@ -117,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'`
|
||||
|
||||
@@ -11,7 +11,7 @@ module Telegram
|
||||
# respond_with :message, text: 'Where are you?'
|
||||
# end
|
||||
#
|
||||
# def set_location_from_messge(city = nil, *)
|
||||
# def set_location_from_message(city = nil, *)
|
||||
# # update
|
||||
# end
|
||||
#
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module Telegram
|
||||
module Bot
|
||||
VERSION = '0.15.4'.freeze
|
||||
VERSION = '0.16.0'.freeze
|
||||
|
||||
def self.gem_version
|
||||
Gem::Version.new VERSION
|
||||
|
||||
@@ -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
|
||||
|
||||
92
spec/telegram/bot/client/request_body_formatter_spec.rb
Обычный файл
92
spec/telegram/bot/client/request_body_formatter_spec.rb
Обычный файл
@@ -0,0 +1,92 @@
|
||||
RSpec.describe Telegram::Bot::Client::RequestBodyFormatter do
|
||||
describe '.format' do
|
||||
subject { described_class.format(input, action) }
|
||||
let(:action) { :sendMessage }
|
||||
|
||||
context 'when plain hash is given' do
|
||||
let(:input) { {a: 1, b: '2', c: nil} }
|
||||
it { should eq input }
|
||||
end
|
||||
|
||||
context 'when nested hash is given' do
|
||||
let(:input) { {a: 1, b: '2', c: [1, 2], d: {a: 1}, e: {b: []}} }
|
||||
|
||||
it 'encodes nested hashes to json' do
|
||||
expected = input.dup
|
||||
%i[c d e].each { |x| expected[x] = expected[x].to_json }
|
||||
should eq expected
|
||||
end
|
||||
end
|
||||
|
||||
context 'with sendMediaGroup action' do
|
||||
let(:action) { :sendMediaGroup }
|
||||
let(:input) { {media: [{a: file_1}, {'b' => file_2, c: 123}, {d: 456}], x: 789} }
|
||||
let(:file_1) { File.new(__FILE__) }
|
||||
let(:file_2) { File.new(__FILE__) }
|
||||
|
||||
it 'extracts files to the top-level' do
|
||||
should eq(
|
||||
media: [
|
||||
{a: 'attach://_file0'},
|
||||
{b: 'attach://_file1', c: 123},
|
||||
{d: 456},
|
||||
].to_json,
|
||||
x: 789,
|
||||
'_file0' => file_1,
|
||||
'_file1' => file_2,
|
||||
)
|
||||
end
|
||||
|
||||
context 'and input has string keys' do
|
||||
let(:input) { super().stringify_keys }
|
||||
it 'extracts files to the top-level' do
|
||||
should eq(
|
||||
'media' => [
|
||||
{a: 'attach://_file0'},
|
||||
{b: 'attach://_file1', c: 123},
|
||||
{d: 456},
|
||||
].to_json,
|
||||
'x' => 789,
|
||||
'_file0' => file_1,
|
||||
'_file1' => file_2,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without media' do
|
||||
let(:input) { {a: 1, b: '2', c: nil} }
|
||||
it { should eq input }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with editMessageMedia action' do
|
||||
let(:action) { :editMessageMedia }
|
||||
let(:input) { {media: {a: file, b: 123}, x: 789} }
|
||||
let(:file) { File.new(__FILE__) }
|
||||
|
||||
it 'extracts files to the top-level' do
|
||||
should eq(
|
||||
media: {a: 'attach://_file0', b: 123}.to_json,
|
||||
x: 789,
|
||||
'_file0' => file,
|
||||
)
|
||||
end
|
||||
|
||||
context 'and input has string keys' do
|
||||
let(:input) { super().stringify_keys }
|
||||
it 'extracts files to the top-level' do
|
||||
should eq(
|
||||
'media' => {a: 'attach://_file0', b: 123}.to_json,
|
||||
'x' => 789,
|
||||
'_file0' => file,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'without media' do
|
||||
let(:input) { {a: 1, b: '2', c: nil} }
|
||||
it { should eq input }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -71,25 +71,6 @@ RSpec.describe Telegram::Bot::Client do
|
||||
end
|
||||
end
|
||||
|
||||
describe '.prepare_body' do
|
||||
subject { described_class.prepare_body(input) }
|
||||
|
||||
context 'when plain hash is given' do
|
||||
let(:input) { {a: 1, b: '2', c: nil} }
|
||||
it { should eq input }
|
||||
end
|
||||
|
||||
context 'when nested hash is given' do
|
||||
let(:input) { {a: 1, b: '2', c: [1, 2], d: {a: 1}, e: {b: []}} }
|
||||
|
||||
it 'encodes nested hashes to json' do
|
||||
expected = input.dup
|
||||
%i[c d e].each { |x| expected[x] = expected[x].to_json }
|
||||
should eq expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.prepare_async_args' do
|
||||
subject { described_class.prepare_async_args(*input) }
|
||||
let(:input) { [:action, a: 1, b: :sym, c: [:other], 'd' => 'str'] }
|
||||
@@ -148,7 +129,8 @@ RSpec.describe Telegram::Bot::Client do
|
||||
let(:body) { body_json.to_json }
|
||||
let(:body_json) { {'param' => 'val', 'description' => 'some description'} }
|
||||
before do
|
||||
expect(described_class).to receive(:prepare_body).with(request_body) { prepared_body }
|
||||
expect(Telegram::Bot::Client::RequestBodyFormatter).
|
||||
to receive(:format).with(request_body, action) { prepared_body }
|
||||
expect(instance).to receive(:http_request).with(url, prepared_body) { response }
|
||||
end
|
||||
around { |ex| Telegram::Bot::ClientStub.stub_all!(false) { ex.run } }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -15,8 +15,9 @@ RSpec.describe Telegram::Bot::UpdatesController::TypedUpdate do
|
||||
edited_channel_post
|
||||
my_chat_member
|
||||
chat_member
|
||||
chat_join_request
|
||||
]).
|
||||
map { |x| [x, Telegram::Bot::Types.const_get(type.camelize)] }.to_h.
|
||||
map { |x| [x, Telegram::Bot::Types.const_get(x.camelize)] }.to_h.
|
||||
merge(
|
||||
'chat_member' => Telegram::Bot::Types::ChatMemberUpdated
|
||||
)
|
||||
|
||||
@@ -46,6 +46,7 @@ RSpec.describe Telegram::Bot::UpdatesController do
|
||||
chosen_inline_result
|
||||
callback_query
|
||||
poll_answer
|
||||
chat_join_request
|
||||
]
|
||||
(described_class::PAYLOAD_TYPES - custom_payload_types).each do |type|
|
||||
context "when payload is #{type}" do
|
||||
|
||||
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
|
||||
|
||||
spec.required_ruby_version = '>= 2.4'
|
||||
|
||||
spec.add_dependency 'actionpack', '>= 4.0', '< 6.2'
|
||||
spec.add_dependency 'activesupport', '>= 4.0', '< 6.2'
|
||||
spec.add_dependency 'actionpack', '>= 4.0', '< 7.2'
|
||||
spec.add_dependency 'activesupport', '>= 4.0', '< 7.2'
|
||||
spec.add_dependency 'httpclient', '~> 2.7'
|
||||
|
||||
spec.add_development_dependency 'bundler', '> 1.16'
|
||||
|
||||
Ссылка в новой задаче
Block a user