зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-09-03 17:55:52 +03:00
Сравнить коммиты
18 Коммитов
| Автор | SHA1 | Дата | |
|---|---|---|---|
|
|
6abbe5489d | ||
|
|
ff7de976d0 | ||
|
|
aaba27eb70 | ||
|
|
88a4a9aab3 | ||
|
|
9387043ec1 | ||
|
|
3dca35ba9a | ||
|
|
6879618c00 | ||
|
|
6e4a69b6b1 | ||
|
|
b8db576452 | ||
|
|
2fffdeb475 | ||
|
|
9defa42f40 | ||
|
|
0320507abe | ||
|
|
cd3d3739a4 | ||
|
|
a054ac704c | ||
|
|
23aa92e614 | ||
|
|
a49dca66fa | ||
|
|
2d5ca981ce | ||
|
|
cf9bd87cf2 |
1
.gitignore
поставляемый
1
.gitignore
поставляемый
@@ -6,4 +6,5 @@
|
|||||||
/doc/
|
/doc/
|
||||||
/pkg/
|
/pkg/
|
||||||
/spec/reports/
|
/spec/reports/
|
||||||
|
/log/
|
||||||
/tmp/
|
/tmp/
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ Style/DotPosition: {EnforcedStyle: trailing}
|
|||||||
Style/FirstParameterIndentation: {EnforcedStyle: consistent}
|
Style/FirstParameterIndentation: {EnforcedStyle: consistent}
|
||||||
Style/IfUnlessModifier: {Enabled: false}
|
Style/IfUnlessModifier: {Enabled: false}
|
||||||
Style/ModuleFunction: {Enabled: false}
|
Style/ModuleFunction: {Enabled: false}
|
||||||
|
Style/MultilineMethodCallIndentation: {EnforcedStyle: indented}
|
||||||
Style/MultilineOperationIndentation: {EnforcedStyle: indented}
|
Style/MultilineOperationIndentation: {EnforcedStyle: indented}
|
||||||
Style/NestedParenthesizedCalls: {Enabled: false}
|
Style/NestedParenthesizedCalls: {Enabled: false}
|
||||||
Style/PredicateName: {Enabled: false}
|
Style/PredicateName: {Enabled: false}
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ rvm:
|
|||||||
env:
|
env:
|
||||||
- RAILS=4
|
- RAILS=4
|
||||||
- RAILS=5
|
- RAILS=5
|
||||||
|
- RAILS=5_1
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
|||||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,6 +1,25 @@
|
|||||||
|
# Unreleased
|
||||||
|
|
||||||
|
# 0.12.0
|
||||||
|
|
||||||
|
- New API methods and payload types (up to Bot API 3.2).
|
||||||
|
- Fix rails 5.1.x support.
|
||||||
|
- RSpec context for callback_query updates.
|
||||||
|
- `edit_message` helper.
|
||||||
|
- ClientStub saves and returns token. Fixes testing multiple bots.
|
||||||
|
- Raise descriptive error when accessing not-configured bot.
|
||||||
|
|
||||||
|
# 0.11.3
|
||||||
|
|
||||||
|
- Release dependencies for Rails 5.1.
|
||||||
|
|
||||||
|
# 0.11.2
|
||||||
|
|
||||||
|
- Rails 5.1 deep symbolized secrets support.
|
||||||
|
|
||||||
# 0.11.1
|
# 0.11.1
|
||||||
|
|
||||||
# Fixed poller for typed response.
|
- Fixed poller for typed response.
|
||||||
|
|
||||||
# 0.11.0
|
# 0.11.0
|
||||||
|
|
||||||
|
|||||||
23
Gemfile
23
Gemfile
@@ -1,14 +1,22 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
case ENV['RAILS']
|
|
||||||
when '5'
|
|
||||||
gem 'actionpack', '5.0.0.rc1'
|
|
||||||
when '4'
|
|
||||||
gem 'actionpack', '~> 4.2'
|
|
||||||
end
|
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
case ENV['RAILS']
|
||||||
|
when '5_1'
|
||||||
|
gem 'railties', '5.1.0'
|
||||||
|
gem 'actionpack', '5.1.0'
|
||||||
|
when '5'
|
||||||
|
gem 'railties', '5.0.2'
|
||||||
|
gem 'actionpack', '5.0.2'
|
||||||
|
when '4'
|
||||||
|
gem 'railties', '~> 4.2'
|
||||||
|
gem 'actionpack', '~> 4.2'
|
||||||
|
else
|
||||||
|
gem 'railties'
|
||||||
|
gem 'actionpack'
|
||||||
|
end
|
||||||
|
|
||||||
gem 'sdoc', '~> 0.4.1'
|
gem 'sdoc', '~> 0.4.1'
|
||||||
gem 'pry', '~> 0.10.1'
|
gem 'pry', '~> 0.10.1'
|
||||||
gem 'pry-byebug', '~> 3.2.0'
|
gem 'pry-byebug', '~> 3.2.0'
|
||||||
@@ -17,6 +25,7 @@ group :development do
|
|||||||
|
|
||||||
gem 'rspec', '~> 3.5.0'
|
gem 'rspec', '~> 3.5.0'
|
||||||
gem 'rspec-its', '~> 1.1.0'
|
gem 'rspec-its', '~> 1.1.0'
|
||||||
|
gem 'rspec-rails', '~> 3.5.0'
|
||||||
|
|
||||||
gem 'rubocop', '~> 0.37.0'
|
gem 'rubocop', '~> 0.37.0'
|
||||||
|
|
||||||
|
|||||||
35
README.md
35
README.md
@@ -27,6 +27,8 @@ Run it on your local machine in 1 minute!
|
|||||||
And here is [app teamplate](https://github.com/telegram-bot-rb/rails_template)
|
And here is [app teamplate](https://github.com/telegram-bot-rb/rails_template)
|
||||||
to generate clean app in seconds.
|
to generate clean app in seconds.
|
||||||
|
|
||||||
|
Examples and cookbook in [wiki](https://github.com/telegram-bot-rb/telegram-bot/wiki).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Add this line to your application's Gemfile:
|
Add this line to your application's Gemfile:
|
||||||
@@ -43,6 +45,12 @@ Or install it yourself as:
|
|||||||
|
|
||||||
$ gem install telegram-bot
|
$ gem install telegram-bot
|
||||||
|
|
||||||
|
Require if necessary:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require 'telegram/bot'
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
@@ -160,6 +168,20 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Reply helpers
|
||||||
|
|
||||||
|
There are helpers to respond for basic actions. They just set chat/message/query
|
||||||
|
identifiers from update. See `ReplyHelpers` method for more information.
|
||||||
|
Here are this methods signatures:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def respond_with(type, params); end
|
||||||
|
def reply_with(type, params); end
|
||||||
|
def answer_inline_query(results, params = {}); end
|
||||||
|
def answer_callback_query(text, params = {}); end
|
||||||
|
def edit_message(type, params = {}); end
|
||||||
|
```
|
||||||
|
|
||||||
#### Optional typecasting
|
#### Optional typecasting
|
||||||
|
|
||||||
You can enable typecasting of `update` with `telegram-bot-types` by including
|
You can enable typecasting of `update` with `telegram-bot-types` by including
|
||||||
@@ -335,6 +357,8 @@ Telegram::Bot::ClientStub.stub_all!
|
|||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# ...
|
# ...
|
||||||
config.after { Telegram.bot.reset }
|
config.after { Telegram.bot.reset }
|
||||||
|
# or for multiple bots:
|
||||||
|
config.after { Telegram.bots.each_value(&:reset) }
|
||||||
# ...
|
# ...
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
@@ -353,6 +377,13 @@ RSpec.describe TelegramWebhooksController, :telegram_bot do
|
|||||||
subject { -> { dispatch_command :start } }
|
subject { -> { dispatch_command :start } }
|
||||||
it { should respond_with_message 'Hi there!' }
|
it { should respond_with_message 'Hi there!' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# There is context for callback queries with related matchers.
|
||||||
|
describe '#hey_callback_query', :callback_query do
|
||||||
|
let(:data) { "hey:#{name}" }
|
||||||
|
let(:name) { 'Joe' }
|
||||||
|
it { should answer_callback_query('Hey Joe') }
|
||||||
|
it { should edit_current_message :text, text: 'Done' }
|
||||||
end
|
end
|
||||||
|
|
||||||
# For controller specs use
|
# For controller specs use
|
||||||
@@ -370,6 +401,10 @@ expect(&process_update).
|
|||||||
to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text'))
|
to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text'))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Place integration tests inside `spec/requests`
|
||||||
|
when using RSpec's `infer_spec_type_from_file_location!`,
|
||||||
|
or just add `type: :request` to `describe`.
|
||||||
|
|
||||||
See sample app for more examples.
|
See sample app for more examples.
|
||||||
|
|
||||||
### Deploying
|
### Deploying
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ require 'active_support/core_ext/hash/keys'
|
|||||||
|
|
||||||
module Telegram
|
module Telegram
|
||||||
module Bot
|
module Bot
|
||||||
class Client
|
class Client # rubocop:disable ClassLength
|
||||||
URL_TEMPLATE = 'https://api.telegram.org/bot%s/'.freeze
|
URL_TEMPLATE = 'https://api.telegram.org/bot%s/'.freeze
|
||||||
|
|
||||||
autoload :TypedResponse, 'telegram/bot/client/typed_response'
|
autoload :TypedResponse, 'telegram/bot/client/typed_response'
|
||||||
@@ -70,6 +70,8 @@ module Telegram
|
|||||||
setWebhook
|
setWebhook
|
||||||
|
|
||||||
answerCallbackQuery
|
answerCallbackQuery
|
||||||
|
deleteChatPhoto
|
||||||
|
exportChatInviteLink
|
||||||
forwardMessage
|
forwardMessage
|
||||||
getChat
|
getChat
|
||||||
getChatAdministrators
|
getChatAdministrators
|
||||||
@@ -80,6 +82,9 @@ module Telegram
|
|||||||
getUserProfilePhotos
|
getUserProfilePhotos
|
||||||
kickChatMember
|
kickChatMember
|
||||||
leaveChat
|
leaveChat
|
||||||
|
pinChatMessage
|
||||||
|
promoteChatMember
|
||||||
|
restrictChatMember
|
||||||
sendAudio
|
sendAudio
|
||||||
sendChatAction
|
sendChatAction
|
||||||
sendContact
|
sendContact
|
||||||
@@ -87,18 +92,35 @@ module Telegram
|
|||||||
sendLocation
|
sendLocation
|
||||||
sendMessage
|
sendMessage
|
||||||
sendPhoto
|
sendPhoto
|
||||||
sendSticker
|
|
||||||
sendVenue
|
sendVenue
|
||||||
sendVideo
|
sendVideo
|
||||||
|
sendVideoNote
|
||||||
sendVoice
|
sendVoice
|
||||||
|
setChatDescription
|
||||||
|
setChatPhoto
|
||||||
|
setChatTitle
|
||||||
unbanChatMember
|
unbanChatMember
|
||||||
|
unpinChatMessage
|
||||||
|
|
||||||
|
deleteMessage
|
||||||
editMessageCaption
|
editMessageCaption
|
||||||
editMessageReplyMarkup
|
editMessageReplyMarkup
|
||||||
editMessageText
|
editMessageText
|
||||||
|
|
||||||
|
sendSticker
|
||||||
|
getStickerSet
|
||||||
|
uploadStickerFile
|
||||||
|
createNewStickerSet
|
||||||
|
addStickerToSet
|
||||||
|
setStickerPositionInSet
|
||||||
|
deleteStickerFromSet
|
||||||
|
|
||||||
answerInlineQuery
|
answerInlineQuery
|
||||||
|
|
||||||
|
sendInvoice
|
||||||
|
answerShippingQuery
|
||||||
|
answerPreCheckoutQuery
|
||||||
|
|
||||||
getGameHighScores
|
getGameHighScores
|
||||||
sendGame
|
sendGame
|
||||||
setGameScore
|
setGameScore
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ module Telegram
|
|||||||
end
|
end
|
||||||
|
|
||||||
def initialize(token = nil, username = nil, **options)
|
def initialize(token = nil, username = nil, **options)
|
||||||
|
@token = token || options[:token]
|
||||||
@username = username || options[:username] || token
|
@username = username || options[:username] || token
|
||||||
reset
|
reset
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
require 'active_support/core_ext/hash/keys'
|
require 'active_support/core_ext/hash/keys'
|
||||||
require 'active_support/core_ext/hash/transform_values'
|
require 'active_support/core_ext/hash/transform_values'
|
||||||
|
require 'active_support/core_ext/hash/indifferent_access'
|
||||||
|
|
||||||
module Telegram
|
module Telegram
|
||||||
module Bot
|
module Bot
|
||||||
@@ -33,7 +34,11 @@ module Telegram
|
|||||||
|
|
||||||
# Default bot.
|
# Default bot.
|
||||||
def bot
|
def bot
|
||||||
@bot ||= bots[:default]
|
@bot ||= bots.fetch(:default) do
|
||||||
|
raise 'Default bot is not configured.' \
|
||||||
|
' Add :default to bots_config' \
|
||||||
|
' or use telegram.bot/telegram.bots.default section in secrets.yml.'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Hash of botan clients made from #bots.
|
# Hash of botan clients made from #bots.
|
||||||
@@ -48,9 +53,10 @@ module Telegram
|
|||||||
def bots_config
|
def bots_config
|
||||||
@bots_config ||=
|
@bots_config ||=
|
||||||
if defined?(Rails.application)
|
if defined?(Rails.application)
|
||||||
telegram_config = Rails.application.secrets[:telegram] || {}
|
secrets = Rails.application.secrets.
|
||||||
(telegram_config['bots'] || {}).symbolize_keys.tap do |config|
|
fetch(:telegram, {}).with_indifferent_access
|
||||||
default = telegram_config['bot']
|
secrets.fetch(:bots, {}).symbolize_keys.tap do |config|
|
||||||
|
default = secrets[:bot]
|
||||||
config[:default] = default if default
|
config[:default] = default if default
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ RSpec.shared_context 'telegram/bot/integration' do
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
let(:clear_session?) { described_class.respond_to?(:session_store) }
|
let(:clear_session?) { described_class.respond_to?(:session_store) }
|
||||||
before { described_class.session_store.clear if clear_session? }
|
before { described_class.session_store.try!(:clear) if clear_session? }
|
||||||
|
|
||||||
include Telegram::Bot::RSpec::ClientMatchers
|
include Telegram::Bot::RSpec::ClientMatchers
|
||||||
|
|
||||||
@@ -36,14 +36,48 @@ RSpec.shared_context 'telegram/bot/integration' do
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Matcher to check response. Make sure to define `let(:chat_id)`.
|
# Matcher to check response. Make sure to define `let(:chat_id)`.
|
||||||
def respond_with_message(expected)
|
def respond_with_message(expected = Regexp.new(''))
|
||||||
raise 'Define chat_id to use respond_with_message' unless defined?(chat_id)
|
raise 'Define chat_id to use respond_with_message' unless defined?(chat_id)
|
||||||
send_telegram_message(bot, expected, chat_id: chat_id)
|
send_telegram_message(bot, expected, chat_id: chat_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
RSpec.shared_context 'telegram/bot/callback_query', callback_query: true do
|
||||||
|
include_context 'telegram/bot/integration'
|
||||||
|
|
||||||
|
subject { -> { dispatch callback_query: payload } }
|
||||||
|
let(:payload) { {id: 11, from: from, message: message, data: data} }
|
||||||
|
let(:message) { {message_id: 22, chat: chat, text: 'message text'} }
|
||||||
|
|
||||||
|
# Matcher to check that origin message got edited.
|
||||||
|
def edit_current_message(type, options = {})
|
||||||
|
description = 'edit current message'
|
||||||
|
options = options.merge(
|
||||||
|
message_id: message[:message_id],
|
||||||
|
chat_id: chat_id,
|
||||||
|
)
|
||||||
|
Telegram::Bot::RSpec::ClientMatchers::MakeTelegramRequest.new(
|
||||||
|
bot, :"editMessage#{type.to_s.camelize}", description: description
|
||||||
|
).with(hash_including(options))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Matcher to check that callback query is answered.
|
||||||
|
def answer_callback_query(text = Regexp.new(''), options = {})
|
||||||
|
description = "answer callback query with #{text.inspect}"
|
||||||
|
text = a_string_matching(text) if text.is_a?(Regexp)
|
||||||
|
options = options.merge(
|
||||||
|
callback_query_id: payload[:id],
|
||||||
|
text: text,
|
||||||
|
)
|
||||||
|
Telegram::Bot::RSpec::ClientMatchers::MakeTelegramRequest.new(
|
||||||
|
bot, :answerCallbackQuery, description: description
|
||||||
|
).with(hash_including(options))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
if config.respond_to?(:include_context)
|
if config.respond_to?(:include_context)
|
||||||
config.include_context 'telegram/bot/integration', :telegram_bot
|
config.include_context 'telegram/bot/integration', :telegram_bot
|
||||||
|
config.include_context 'telegram/bot/callback_query', :telegram_bot, :callback_query
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ module Telegram
|
|||||||
inline_query
|
inline_query
|
||||||
chosen_inline_result
|
chosen_inline_result
|
||||||
callback_query
|
callback_query
|
||||||
|
shipping_query
|
||||||
|
pre_checkout_query
|
||||||
).freeze
|
).freeze
|
||||||
CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i
|
CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i
|
||||||
CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)")
|
CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)")
|
||||||
@@ -169,15 +171,21 @@ module Telegram
|
|||||||
# Returns array `[is_command?, action, args]`.
|
# Returns array `[is_command?, action, args]`.
|
||||||
def action_for_payload
|
def action_for_payload
|
||||||
if payload_type
|
if payload_type
|
||||||
send("action_for_#{payload_type}") || [false, payload_type, [payload]]
|
send("action_for_#{payload_type}") || action_for_default_payload
|
||||||
else
|
else
|
||||||
[false, :unsupported_payload_type, []]
|
[false, :unsupported_payload_type, []]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def action_for_default_payload
|
||||||
|
[false, payload_type, [payload]]
|
||||||
|
end
|
||||||
|
|
||||||
# If payload is a message with command, then returned action is an
|
# If payload is a message with command, then returned action is an
|
||||||
# action for this command.
|
# action for this command.
|
||||||
# Separate method, so it can be easily overriden (ex. MessageContext).
|
# Separate method, so it can be easily overriden (ex. MessageContext).
|
||||||
|
#
|
||||||
|
# This is not used for edited messages/posts. It process them as basic updates.
|
||||||
def action_for_message
|
def action_for_message
|
||||||
cmd, args = self.class.command_from_text(payload['text'], bot_username)
|
cmd, args = self.class.command_from_text(payload['text'], bot_username)
|
||||||
cmd &&= self.class.action_for_command(cmd)
|
cmd &&= self.class.action_for_command(cmd)
|
||||||
@@ -185,12 +193,6 @@ module Telegram
|
|||||||
end
|
end
|
||||||
alias_method :action_for_channel_post, :action_for_message
|
alias_method :action_for_channel_post, :action_for_message
|
||||||
|
|
||||||
# It doesn't extract commands from edited messages. Just process
|
|
||||||
# them as usual ones.
|
|
||||||
def action_for_edited_message
|
|
||||||
end
|
|
||||||
alias_method :action_for_edited_channel_post, :action_for_edited_message
|
|
||||||
|
|
||||||
def action_for_inline_query
|
def action_for_inline_query
|
||||||
[false, payload_type, [payload['query'], payload['offset']]]
|
[false, payload_type, [payload['query'], payload['offset']]]
|
||||||
end
|
end
|
||||||
@@ -208,6 +210,11 @@ module Telegram
|
|||||||
def action_missing(*)
|
def action_missing(*)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
PAYLOAD_TYPES.each do |type|
|
||||||
|
method = :"action_for_#{type}"
|
||||||
|
alias_method method, :action_for_default_payload unless instance_methods.include?(method)
|
||||||
|
end
|
||||||
|
|
||||||
ActiveSupport.run_load_hooks('telegram.bot.updates_controller', self)
|
ActiveSupport.run_load_hooks('telegram.bot.updates_controller', self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ module Telegram
|
|||||||
# because `data` param is controlled by client.
|
# because `data` param is controlled by client.
|
||||||
def action_for_callback_query
|
def action_for_callback_query
|
||||||
context, new_data = context_from_callback_query
|
context, new_data = context_from_callback_query
|
||||||
# binding.pry
|
|
||||||
if context
|
if context
|
||||||
action_name = "#{context}_callback_query"
|
action_name = "#{context}_callback_query"
|
||||||
[false, action_name, [new_data]] if action_method?(action_name)
|
[false, action_name, [new_data]] if action_method?(action_name)
|
||||||
|
|||||||
@@ -38,6 +38,19 @@ module Telegram
|
|||||||
)
|
)
|
||||||
bot.answer_callback_query(params)
|
bot.answer_callback_query(params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Edit message from callback query.
|
||||||
|
def edit_message(type, params = {})
|
||||||
|
params =
|
||||||
|
if message_id = payload['inline_message_id'] # rubocop:disable AssignmentInCondition
|
||||||
|
params.merge(inline_message_id: message_id)
|
||||||
|
elsif message = payload['message'] # rubocop:disable AssignmentInCondition
|
||||||
|
params.merge(chat_id: message['chat']['id'], message_id: message['message_id'])
|
||||||
|
else
|
||||||
|
raise 'Can not edit message without `inline_message_id` or `message`'
|
||||||
|
end
|
||||||
|
bot.public_send("edit_message_#{type}", params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module Telegram
|
module Telegram
|
||||||
module Bot
|
module Bot
|
||||||
VERSION = '0.11.1'.freeze
|
VERSION = '0.12.0'.freeze
|
||||||
|
|
||||||
def self.gem_version
|
def self.gem_version
|
||||||
Gem::Version.new VERSION
|
Gem::Version.new VERSION
|
||||||
|
|||||||
8
spec/integration/requests/default_bot_spec.rb
Обычный файл
8
spec/integration/requests/default_bot_spec.rb
Обычный файл
@@ -0,0 +1,8 @@
|
|||||||
|
require 'integration_helper'
|
||||||
|
|
||||||
|
RSpec.describe DefaultBotController, :telegram_bot, type: :request do
|
||||||
|
describe '#start' do
|
||||||
|
subject { -> { dispatch_command :start } }
|
||||||
|
it { should respond_with_message 'from default' }
|
||||||
|
end
|
||||||
|
end
|
||||||
9
spec/integration/requests/named_bot_spec.rb
Обычный файл
9
spec/integration/requests/named_bot_spec.rb
Обычный файл
@@ -0,0 +1,9 @@
|
|||||||
|
require 'integration_helper'
|
||||||
|
|
||||||
|
RSpec.describe NamedBotController, :telegram_bot, type: :request do
|
||||||
|
let(:bot) { Telegram.bots[:named] }
|
||||||
|
describe '#start' do
|
||||||
|
subject { -> { dispatch_command :start } }
|
||||||
|
it { should respond_with_message 'from named' }
|
||||||
|
end
|
||||||
|
end
|
||||||
9
spec/integration/requests/other_bot_spec.rb
Обычный файл
9
spec/integration/requests/other_bot_spec.rb
Обычный файл
@@ -0,0 +1,9 @@
|
|||||||
|
require 'integration_helper'
|
||||||
|
|
||||||
|
RSpec.describe OtherBotController, :telegram_bot, type: :request do
|
||||||
|
let(:bot) { Telegram.bots[:other] }
|
||||||
|
describe '#start' do
|
||||||
|
subject { -> { dispatch_command :start } }
|
||||||
|
it { should respond_with_message 'from other' }
|
||||||
|
end
|
||||||
|
end
|
||||||
62
spec/integration_helper.rb
Обычный файл
62
spec/integration_helper.rb
Обычный файл
@@ -0,0 +1,62 @@
|
|||||||
|
require 'telegram/bot/rspec/integration'
|
||||||
|
require 'action_controller'
|
||||||
|
require 'action_dispatch'
|
||||||
|
require 'action_dispatch/testing/integration'
|
||||||
|
|
||||||
|
require 'rails'
|
||||||
|
require 'rspec/rails/adapters'
|
||||||
|
require 'rspec/rails/fixture_support'
|
||||||
|
require 'rspec/rails/example/rails_example_group'
|
||||||
|
require 'rspec/rails/example/request_example_group'
|
||||||
|
|
||||||
|
ENV['RAILS_ENV'] = 'test'
|
||||||
|
class TestApplication < Rails::Application
|
||||||
|
config.eager_load = false
|
||||||
|
config.log_level = :debug
|
||||||
|
secrets[:secret_key_base] = 'test'
|
||||||
|
secrets[:telegram] = {
|
||||||
|
bot: 'default_token',
|
||||||
|
bots: {
|
||||||
|
other: {token: 'other_token'},
|
||||||
|
named: {token: 'named_token', username: 'TestBot'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
Rails.application.initialize!
|
||||||
|
|
||||||
|
# # Controllers
|
||||||
|
%w(default other named).each do |bot_name|
|
||||||
|
controller = Class.new(Telegram::Bot::UpdatesController) do
|
||||||
|
define_method :start do |*|
|
||||||
|
respond_with :message, text: "from #{bot_name}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Object.const_set("#{bot_name}_bot_controller".camelize, controller)
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec.configure do |config|
|
||||||
|
config.include RSpec::Rails::RequestExampleGroup, type: :request
|
||||||
|
|
||||||
|
config.around type: :request do |ex|
|
||||||
|
begin
|
||||||
|
Telegram.reset_bots
|
||||||
|
Telegram::Bot::ClientStub.stub_all!
|
||||||
|
ex.run
|
||||||
|
ensure
|
||||||
|
Telegram.reset_bots
|
||||||
|
Telegram::Bot::ClientStub.stub_all!(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
config.before type: :request do
|
||||||
|
# Redefine routes before every example, so it does not depent on order.
|
||||||
|
Rails.application.routes.draw do
|
||||||
|
require 'telegram/bot/routes_helper'
|
||||||
|
extend Telegram::Bot::RoutesHelper
|
||||||
|
|
||||||
|
telegram_webhooks default: DefaultBotController,
|
||||||
|
other: OtherBotController,
|
||||||
|
named: NamedBotController
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -46,8 +46,14 @@ RSpec.describe Telegram::Bot::ClientStub do
|
|||||||
|
|
||||||
context 'when username and token are given' do
|
context 'when username and token are given' do
|
||||||
let(:args) { %w(token superbot) }
|
let(:args) { %w(token superbot) }
|
||||||
its(:token) { should eq nil }
|
its(:token) { should eq args[0] }
|
||||||
its(:username) { should eq args[1] }
|
its(:username) { should eq args[1] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when hash config is given' do
|
||||||
|
let(:args) { [token: 'token', username: 'superbot'] }
|
||||||
|
its(:token) { should eq args[0][:token] }
|
||||||
|
its(:username) { should eq args[0][:username] }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,8 +22,13 @@ RSpec.describe Telegram::Bot::ConfigMethods do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#bot' do
|
describe '#bot' do
|
||||||
subject { registry.bot }
|
subject { -> { registry.bot } }
|
||||||
it { should eq registry.bots[:default] }
|
its(:call) { should eq registry.bots[:default] }
|
||||||
|
|
||||||
|
context 'when bot is not configured' do
|
||||||
|
let(:config) { super().except(:default) }
|
||||||
|
it { should raise_error(/bot is not configured/) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#bots' do
|
describe '#bots' do
|
||||||
@@ -67,6 +72,7 @@ RSpec.describe Telegram::Bot::ConfigMethods do
|
|||||||
|
|
||||||
context 'when not configured' do
|
context 'when not configured' do
|
||||||
let(:registry) { Object.new.tap { |x| x.extend described_class } }
|
let(:registry) { Object.new.tap { |x| x.extend described_class } }
|
||||||
|
before { hide_const('Rails') }
|
||||||
it { should eq({}) }
|
it { should eq({}) }
|
||||||
|
|
||||||
context 'in rails environment' do
|
context 'in rails environment' do
|
||||||
@@ -87,6 +93,12 @@ RSpec.describe Telegram::Bot::ConfigMethods do
|
|||||||
end
|
end
|
||||||
it { should include default: config[:bot] }
|
it { should include default: config[:bot] }
|
||||||
it { should include config[:bots] }
|
it { should include config[:bots] }
|
||||||
|
|
||||||
|
context 'on rails >5.1 (deep symbolized keys)' do
|
||||||
|
let(:secrets) { {telegram: config.deep_symbolize_keys} }
|
||||||
|
it { should include default: config[:bot] }
|
||||||
|
it { should include config[:bots] }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -48,4 +48,32 @@ RSpec.describe Telegram::Bot::UpdatesController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#edit_message' do
|
||||||
|
subject { controller.edit_message(type, params) }
|
||||||
|
let(:type) { :reply_markup }
|
||||||
|
|
||||||
|
it { expect { subject }.to raise_error(/Can not edit message without/) }
|
||||||
|
|
||||||
|
context 'when inline_message_id is present' do
|
||||||
|
let(:payload) { {inline_message_id: double(:message_id)} }
|
||||||
|
it 'sets inline_message_id' do
|
||||||
|
expect(bot).to receive("edit_message_#{type}").with(params.merge(
|
||||||
|
inline_message_id: payload[:inline_message_id],
|
||||||
|
)) { result }
|
||||||
|
should eq result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when message is present' do
|
||||||
|
let(:payload) { {message: super().merge(chat: chat)} }
|
||||||
|
it 'sets chat_id & message_id' do
|
||||||
|
expect(bot).to receive("edit_message_#{type}").with(params.merge(
|
||||||
|
message_id: payload[:message][:message_id],
|
||||||
|
chat_id: payload[:message][:chat]['id'],
|
||||||
|
)) { result }
|
||||||
|
should eq result
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ RSpec.describe Telegram::Bot::UpdatesController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
%w(message channel_post).each do |type|
|
%w(message channel_post).each do |type|
|
||||||
context 'when payload is edited_message' do
|
context "when payload is edited_#{type}" do
|
||||||
let(:payload_type) { "edited_#{type}" }
|
let(:payload_type) { "edited_#{type}" }
|
||||||
it { should eq [false, payload_type, [payload]] }
|
it { should eq [false, payload_type, [payload]] }
|
||||||
end
|
end
|
||||||
@@ -142,6 +142,22 @@ RSpec.describe Telegram::Bot::UpdatesController do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
custom_payload_types = %w(
|
||||||
|
message
|
||||||
|
edited_message
|
||||||
|
channel_post
|
||||||
|
edited_channel_post
|
||||||
|
inline_query
|
||||||
|
chosen_inline_result
|
||||||
|
callback_query
|
||||||
|
)
|
||||||
|
(described_class::PAYLOAD_TYPES - custom_payload_types).each do |type|
|
||||||
|
context "when payload is #{type}" do
|
||||||
|
let(:payload_type) { type }
|
||||||
|
it { should eq [false, payload_type, [payload]] }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when `update` is a virtus model' do
|
context 'when `update` is a virtus model' do
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|||||||
|
|
||||||
spec.required_ruby_version = '~> 2.0'
|
spec.required_ruby_version = '~> 2.0'
|
||||||
|
|
||||||
spec.add_dependency 'activesupport', '>= 4.0', '< 5.1'
|
spec.add_dependency 'activesupport', '>= 4.0', '< 5.2'
|
||||||
spec.add_dependency 'actionpack', '>= 4.0', '< 5.1'
|
spec.add_dependency 'actionpack', '>= 4.0', '< 5.2'
|
||||||
spec.add_dependency 'httpclient', '~> 2.7'
|
spec.add_dependency 'httpclient', '~> 2.7'
|
||||||
spec.add_development_dependency 'bundler', '~> 1.11'
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
||||||
spec.add_development_dependency 'rake', '~> 10.0'
|
spec.add_development_dependency 'rake', '~> 10.0'
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user