telegram-bot 0.11.3 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile +16 -9
- data/README.md +29 -0
- data/lib/telegram/bot/client.rb +24 -2
- data/lib/telegram/bot/client_stub.rb +1 -0
- data/lib/telegram/bot/config_methods.rb +5 -1
- data/lib/telegram/bot/rspec/integration.rb +36 -2
- data/lib/telegram/bot/updates_controller.rb +14 -7
- data/lib/telegram/bot/updates_controller/callback_query_context.rb +0 -1
- data/lib/telegram/bot/updates_controller/reply_helpers.rb +13 -0
- data/lib/telegram/bot/version.rb +1 -1
- data/telegram-bot.gemspec +2 -2
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21e86ff6949e2e4f60350c86344291f603bafc8c
|
4
|
+
data.tar.gz: 61478f30a26e0ae4e50c18fd34e2df250dba9fe3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1eb9064cd9b8220b8d47f436422d2088cb03e44c35bec3590c59f8e26f79a36e049f36b5761bcbf73854bb168f38c0201ce6bd5253c590049f201be5aa4dcae
|
7
|
+
data.tar.gz: e405a0acf8966a581f6efc65b893a5746ff614382ccfa32d051ec3c60d78f9a83be4756f25b62178118251659d1c58d4704a2c48c05c3a6ddb5d2a0fca2b77ac
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# Unreleased
|
2
|
+
|
3
|
+
# 0.12.0
|
4
|
+
|
5
|
+
- New API methods and payload types (up to Bot API 3.2).
|
6
|
+
- Fix rails 5.1.x support.
|
7
|
+
- RSpec context for callback_query updates.
|
8
|
+
- `edit_message` helper.
|
9
|
+
- ClientStub saves and returns token. Fixes testing multiple bots.
|
10
|
+
- Raise descriptive error when accessing not-configured bot.
|
11
|
+
|
1
12
|
# 0.11.3
|
2
13
|
|
3
14
|
- Release dependencies for Rails 5.1.
|
data/Gemfile
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
gemspec
|
3
3
|
|
4
|
-
case ENV['RAILS']
|
5
|
-
when '5_1'
|
6
|
-
gem 'actionpack', '5.1.0'
|
7
|
-
when '5'
|
8
|
-
gem 'actionpack', '5.0.2'
|
9
|
-
when '4'
|
10
|
-
gem 'actionpack', '~> 4.2'
|
11
|
-
end
|
12
|
-
|
13
4
|
group :development do
|
5
|
+
case ENV['RAILS']
|
6
|
+
when '5_1'
|
7
|
+
gem 'railties', '5.1.0'
|
8
|
+
gem 'actionpack', '5.1.0'
|
9
|
+
when '5'
|
10
|
+
gem 'railties', '5.0.2'
|
11
|
+
gem 'actionpack', '5.0.2'
|
12
|
+
when '4'
|
13
|
+
gem 'railties', '~> 4.2'
|
14
|
+
gem 'actionpack', '~> 4.2'
|
15
|
+
else
|
16
|
+
gem 'railties'
|
17
|
+
gem 'actionpack'
|
18
|
+
end
|
19
|
+
|
14
20
|
gem 'sdoc', '~> 0.4.1'
|
15
21
|
gem 'pry', '~> 0.10.1'
|
16
22
|
gem 'pry-byebug', '~> 3.2.0'
|
@@ -19,6 +25,7 @@ group :development do
|
|
19
25
|
|
20
26
|
gem 'rspec', '~> 3.5.0'
|
21
27
|
gem 'rspec-its', '~> 1.1.0'
|
28
|
+
gem 'rspec-rails', '~> 3.5.0'
|
22
29
|
|
23
30
|
gem 'rubocop', '~> 0.37.0'
|
24
31
|
|
data/README.md
CHANGED
@@ -27,6 +27,8 @@ Run it on your local machine in 1 minute!
|
|
27
27
|
And here is [app teamplate](https://github.com/telegram-bot-rb/rails_template)
|
28
28
|
to generate clean app in seconds.
|
29
29
|
|
30
|
+
Examples and cookbook in [wiki](https://github.com/telegram-bot-rb/telegram-bot/wiki).
|
31
|
+
|
30
32
|
## Installation
|
31
33
|
|
32
34
|
Add this line to your application's Gemfile:
|
@@ -166,6 +168,20 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
|
|
166
168
|
end
|
167
169
|
```
|
168
170
|
|
171
|
+
#### Reply helpers
|
172
|
+
|
173
|
+
There are helpers to respond for basic actions. They just set chat/message/query
|
174
|
+
identifiers from update. See `ReplyHelpers` method for more information.
|
175
|
+
Here are this methods signatures:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
def respond_with(type, params); end
|
179
|
+
def reply_with(type, params); end
|
180
|
+
def answer_inline_query(results, params = {}); end
|
181
|
+
def answer_callback_query(text, params = {}); end
|
182
|
+
def edit_message(type, params = {}); end
|
183
|
+
```
|
184
|
+
|
169
185
|
#### Optional typecasting
|
170
186
|
|
171
187
|
You can enable typecasting of `update` with `telegram-bot-types` by including
|
@@ -341,6 +357,8 @@ Telegram::Bot::ClientStub.stub_all!
|
|
341
357
|
RSpec.configure do |config|
|
342
358
|
# ...
|
343
359
|
config.after { Telegram.bot.reset }
|
360
|
+
# or for multiple bots:
|
361
|
+
config.after { Telegram.bots.each_value(&:reset) }
|
344
362
|
# ...
|
345
363
|
end
|
346
364
|
```
|
@@ -359,6 +377,13 @@ RSpec.describe TelegramWebhooksController, :telegram_bot do
|
|
359
377
|
subject { -> { dispatch_command :start } }
|
360
378
|
it { should respond_with_message 'Hi there!' }
|
361
379
|
end
|
380
|
+
|
381
|
+
# There is context for callback queries with related matchers.
|
382
|
+
describe '#hey_callback_query', :callback_query do
|
383
|
+
let(:data) { "hey:#{name}" }
|
384
|
+
let(:name) { 'Joe' }
|
385
|
+
it { should answer_callback_query('Hey Joe') }
|
386
|
+
it { should edit_current_message :text, text: 'Done' }
|
362
387
|
end
|
363
388
|
|
364
389
|
# For controller specs use
|
@@ -376,6 +401,10 @@ expect(&process_update).
|
|
376
401
|
to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text'))
|
377
402
|
```
|
378
403
|
|
404
|
+
Place integration tests inside `spec/requests`
|
405
|
+
when using RSpec's `infer_spec_type_from_file_location!`,
|
406
|
+
or just add `type: :request` to `describe`.
|
407
|
+
|
379
408
|
See sample app for more examples.
|
380
409
|
|
381
410
|
### Deploying
|
data/lib/telegram/bot/client.rb
CHANGED
@@ -5,7 +5,7 @@ require 'active_support/core_ext/hash/keys'
|
|
5
5
|
|
6
6
|
module Telegram
|
7
7
|
module Bot
|
8
|
-
class Client
|
8
|
+
class Client # rubocop:disable ClassLength
|
9
9
|
URL_TEMPLATE = 'https://api.telegram.org/bot%s/'.freeze
|
10
10
|
|
11
11
|
autoload :TypedResponse, 'telegram/bot/client/typed_response'
|
@@ -70,6 +70,8 @@ module Telegram
|
|
70
70
|
setWebhook
|
71
71
|
|
72
72
|
answerCallbackQuery
|
73
|
+
deleteChatPhoto
|
74
|
+
exportChatInviteLink
|
73
75
|
forwardMessage
|
74
76
|
getChat
|
75
77
|
getChatAdministrators
|
@@ -80,6 +82,9 @@ module Telegram
|
|
80
82
|
getUserProfilePhotos
|
81
83
|
kickChatMember
|
82
84
|
leaveChat
|
85
|
+
pinChatMessage
|
86
|
+
promoteChatMember
|
87
|
+
restrictChatMember
|
83
88
|
sendAudio
|
84
89
|
sendChatAction
|
85
90
|
sendContact
|
@@ -87,18 +92,35 @@ module Telegram
|
|
87
92
|
sendLocation
|
88
93
|
sendMessage
|
89
94
|
sendPhoto
|
90
|
-
sendSticker
|
91
95
|
sendVenue
|
92
96
|
sendVideo
|
97
|
+
sendVideoNote
|
93
98
|
sendVoice
|
99
|
+
setChatDescription
|
100
|
+
setChatPhoto
|
101
|
+
setChatTitle
|
94
102
|
unbanChatMember
|
103
|
+
unpinChatMessage
|
95
104
|
|
105
|
+
deleteMessage
|
96
106
|
editMessageCaption
|
97
107
|
editMessageReplyMarkup
|
98
108
|
editMessageText
|
99
109
|
|
110
|
+
sendSticker
|
111
|
+
getStickerSet
|
112
|
+
uploadStickerFile
|
113
|
+
createNewStickerSet
|
114
|
+
addStickerToSet
|
115
|
+
setStickerPositionInSet
|
116
|
+
deleteStickerFromSet
|
117
|
+
|
100
118
|
answerInlineQuery
|
101
119
|
|
120
|
+
sendInvoice
|
121
|
+
answerShippingQuery
|
122
|
+
answerPreCheckoutQuery
|
123
|
+
|
102
124
|
getGameHighScores
|
103
125
|
sendGame
|
104
126
|
setGameScore
|
@@ -34,7 +34,11 @@ module Telegram
|
|
34
34
|
|
35
35
|
# Default bot.
|
36
36
|
def bot
|
37
|
-
@bot ||= bots
|
37
|
+
@bot ||= bots.fetch(:default) do
|
38
|
+
raise 'Default bot is not configured.' \
|
39
|
+
' Add :default to bots_config' \
|
40
|
+
' or use telegram.bot/telegram.bots.default section in secrets.yml.'
|
41
|
+
end
|
38
42
|
end
|
39
43
|
|
40
44
|
# Hash of botan clients made from #bots.
|
@@ -14,7 +14,7 @@ RSpec.shared_context 'telegram/bot/integration' do
|
|
14
14
|
}
|
15
15
|
end
|
16
16
|
let(:clear_session?) { described_class.respond_to?(:session_store) }
|
17
|
-
before { described_class.session_store.clear if clear_session? }
|
17
|
+
before { described_class.session_store.try!(:clear) if clear_session? }
|
18
18
|
|
19
19
|
include Telegram::Bot::RSpec::ClientMatchers
|
20
20
|
|
@@ -36,14 +36,48 @@ RSpec.shared_context 'telegram/bot/integration' do
|
|
36
36
|
end
|
37
37
|
|
38
38
|
# Matcher to check response. Make sure to define `let(:chat_id)`.
|
39
|
-
def respond_with_message(expected)
|
39
|
+
def respond_with_message(expected = Regexp.new(''))
|
40
40
|
raise 'Define chat_id to use respond_with_message' unless defined?(chat_id)
|
41
41
|
send_telegram_message(bot, expected, chat_id: chat_id)
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
RSpec.shared_context 'telegram/bot/callback_query', callback_query: true do
|
46
|
+
include_context 'telegram/bot/integration'
|
47
|
+
|
48
|
+
subject { -> { dispatch callback_query: payload } }
|
49
|
+
let(:payload) { {id: 11, from: from, message: message, data: data} }
|
50
|
+
let(:message) { {message_id: 22, chat: chat, text: 'message text'} }
|
51
|
+
|
52
|
+
# Matcher to check that origin message got edited.
|
53
|
+
def edit_current_message(type, options = {})
|
54
|
+
description = 'edit current message'
|
55
|
+
options = options.merge(
|
56
|
+
message_id: message[:message_id],
|
57
|
+
chat_id: chat_id,
|
58
|
+
)
|
59
|
+
Telegram::Bot::RSpec::ClientMatchers::MakeTelegramRequest.new(
|
60
|
+
bot, :"editMessage#{type.to_s.camelize}", description: description
|
61
|
+
).with(hash_including(options))
|
62
|
+
end
|
63
|
+
|
64
|
+
# Matcher to check that callback query is answered.
|
65
|
+
def answer_callback_query(text = Regexp.new(''), options = {})
|
66
|
+
description = "answer callback query with #{text.inspect}"
|
67
|
+
text = a_string_matching(text) if text.is_a?(Regexp)
|
68
|
+
options = options.merge(
|
69
|
+
callback_query_id: payload[:id],
|
70
|
+
text: text,
|
71
|
+
)
|
72
|
+
Telegram::Bot::RSpec::ClientMatchers::MakeTelegramRequest.new(
|
73
|
+
bot, :answerCallbackQuery, description: description
|
74
|
+
).with(hash_including(options))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
45
78
|
RSpec.configure do |config|
|
46
79
|
if config.respond_to?(:include_context)
|
47
80
|
config.include_context 'telegram/bot/integration', :telegram_bot
|
81
|
+
config.include_context 'telegram/bot/callback_query', :telegram_bot, :callback_query
|
48
82
|
end
|
49
83
|
end
|
@@ -86,6 +86,8 @@ module Telegram
|
|
86
86
|
inline_query
|
87
87
|
chosen_inline_result
|
88
88
|
callback_query
|
89
|
+
shipping_query
|
90
|
+
pre_checkout_query
|
89
91
|
).freeze
|
90
92
|
CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i
|
91
93
|
CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)")
|
@@ -169,15 +171,21 @@ module Telegram
|
|
169
171
|
# Returns array `[is_command?, action, args]`.
|
170
172
|
def action_for_payload
|
171
173
|
if payload_type
|
172
|
-
send("action_for_#{payload_type}") ||
|
174
|
+
send("action_for_#{payload_type}") || action_for_default_payload
|
173
175
|
else
|
174
176
|
[false, :unsupported_payload_type, []]
|
175
177
|
end
|
176
178
|
end
|
177
179
|
|
180
|
+
def action_for_default_payload
|
181
|
+
[false, payload_type, [payload]]
|
182
|
+
end
|
183
|
+
|
178
184
|
# If payload is a message with command, then returned action is an
|
179
185
|
# action for this command.
|
180
186
|
# Separate method, so it can be easily overriden (ex. MessageContext).
|
187
|
+
#
|
188
|
+
# This is not used for edited messages/posts. It process them as basic updates.
|
181
189
|
def action_for_message
|
182
190
|
cmd, args = self.class.command_from_text(payload['text'], bot_username)
|
183
191
|
cmd &&= self.class.action_for_command(cmd)
|
@@ -185,12 +193,6 @@ module Telegram
|
|
185
193
|
end
|
186
194
|
alias_method :action_for_channel_post, :action_for_message
|
187
195
|
|
188
|
-
# It doesn't extract commands from edited messages. Just process
|
189
|
-
# them as usual ones.
|
190
|
-
def action_for_edited_message
|
191
|
-
end
|
192
|
-
alias_method :action_for_edited_channel_post, :action_for_edited_message
|
193
|
-
|
194
196
|
def action_for_inline_query
|
195
197
|
[false, payload_type, [payload['query'], payload['offset']]]
|
196
198
|
end
|
@@ -208,6 +210,11 @@ module Telegram
|
|
208
210
|
def action_missing(*)
|
209
211
|
end
|
210
212
|
|
213
|
+
PAYLOAD_TYPES.each do |type|
|
214
|
+
method = :"action_for_#{type}"
|
215
|
+
alias_method method, :action_for_default_payload unless instance_methods.include?(method)
|
216
|
+
end
|
217
|
+
|
211
218
|
ActiveSupport.run_load_hooks('telegram.bot.updates_controller', self)
|
212
219
|
end
|
213
220
|
end
|
@@ -15,7 +15,6 @@ module Telegram
|
|
15
15
|
# because `data` param is controlled by client.
|
16
16
|
def action_for_callback_query
|
17
17
|
context, new_data = context_from_callback_query
|
18
|
-
# binding.pry
|
19
18
|
if context
|
20
19
|
action_name = "#{context}_callback_query"
|
21
20
|
[false, action_name, [new_data]] if action_method?(action_name)
|
@@ -38,6 +38,19 @@ module Telegram
|
|
38
38
|
)
|
39
39
|
bot.answer_callback_query(params)
|
40
40
|
end
|
41
|
+
|
42
|
+
# Edit message from callback query.
|
43
|
+
def edit_message(type, params = {})
|
44
|
+
params =
|
45
|
+
if message_id = payload['inline_message_id'] # rubocop:disable AssignmentInCondition
|
46
|
+
params.merge(inline_message_id: message_id)
|
47
|
+
elsif message = payload['message'] # rubocop:disable AssignmentInCondition
|
48
|
+
params.merge(chat_id: message['chat']['id'], message_id: message['message_id'])
|
49
|
+
else
|
50
|
+
raise 'Can not edit message without `inline_message_id` or `message`'
|
51
|
+
end
|
52
|
+
bot.public_send("edit_message_#{type}", params)
|
53
|
+
end
|
41
54
|
end
|
42
55
|
end
|
43
56
|
end
|
data/lib/telegram/bot/version.rb
CHANGED
data/telegram-bot.gemspec
CHANGED
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.required_ruby_version = '~> 2.0'
|
22
22
|
|
23
|
-
spec.add_dependency 'activesupport', '>= 4.0', '
|
24
|
-
spec.add_dependency 'actionpack', '>= 4.0', '
|
23
|
+
spec.add_dependency 'activesupport', '>= 4.0', '< 5.2'
|
24
|
+
spec.add_dependency 'actionpack', '>= 4.0', '< 5.2'
|
25
25
|
spec.add_dependency 'httpclient', '~> 2.7'
|
26
26
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
27
27
|
spec.add_development_dependency 'rake', '~> 10.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: telegram-bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max Melentiev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -17,9 +17,9 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.0'
|
20
|
-
- - "
|
20
|
+
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '5.
|
22
|
+
version: '5.2'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +27,9 @@ dependencies:
|
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '4.0'
|
30
|
-
- - "
|
30
|
+
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '5.
|
32
|
+
version: '5.2'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: actionpack
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -37,9 +37,9 @@ dependencies:
|
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '4.0'
|
40
|
-
- - "
|
40
|
+
- - "<"
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '5.
|
42
|
+
version: '5.2'
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -47,9 +47,9 @@ dependencies:
|
|
47
47
|
- - ">="
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: '4.0'
|
50
|
-
- - "
|
50
|
+
- - "<"
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: '5.
|
52
|
+
version: '5.2'
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: httpclient
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|