telegram-bot 0.11.3 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 90fe9ba02f559d7627de3c66909da6815bac5e96
4
- data.tar.gz: 9eece5573e375b2443752987b6788c443a369833
3
+ metadata.gz: 21e86ff6949e2e4f60350c86344291f603bafc8c
4
+ data.tar.gz: 61478f30a26e0ae4e50c18fd34e2df250dba9fe3
5
5
  SHA512:
6
- metadata.gz: 76fbe6456c485ed85b052177ec3d759487cb0e96c0db8891286a49a198be4832891b82751de3817e6b913640cd042ee00d69e4067d8146402695cea28aa8b691
7
- data.tar.gz: 8ae9a9fcaa9a771b60149e0350f6f18377e67788d26cb40fe9ce38e1d837282865608b4034506e294cab8617492954653ffdb368cf3a71f92e5d2e41bf4a7151
6
+ metadata.gz: f1eb9064cd9b8220b8d47f436422d2088cb03e44c35bec3590c59f8e26f79a36e049f36b5761bcbf73854bb168f38c0201ce6bd5253c590049f201be5aa4dcae
7
+ data.tar.gz: e405a0acf8966a581f6efc65b893a5746ff614382ccfa32d051ec3c60d78f9a83be4756f25b62178118251659d1c58d4704a2c48c05c3a6ddb5d2a0fca2b77ac
data/.gitignore CHANGED
@@ -6,4 +6,5 @@
6
6
  /doc/
7
7
  /pkg/
8
8
  /spec/reports/
9
+ /log/
9
10
  /tmp/
@@ -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
@@ -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
@@ -35,6 +35,7 @@ module Telegram
35
35
  end
36
36
 
37
37
  def initialize(token = nil, username = nil, **options)
38
+ @token = token || options[:token]
38
39
  @username = username || options[:username] || token
39
40
  reset
40
41
  end
@@ -34,7 +34,11 @@ module Telegram
34
34
 
35
35
  # Default bot.
36
36
  def bot
37
- @bot ||= bots[:default]
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}") || [false, payload_type, [payload]]
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
@@ -1,6 +1,6 @@
1
1
  module Telegram
2
2
  module Bot
3
- VERSION = '0.11.3'.freeze
3
+ VERSION = '0.12.0'.freeze
4
4
 
5
5
  def self.gem_version
6
6
  Gem::Version.new VERSION
@@ -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', '<= 5.1'
24
- spec.add_dependency 'actionpack', '>= 4.0', '<= 5.1'
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.11.3
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-05-05 00:00:00.000000000 Z
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.1'
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.1'
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.1'
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.1'
52
+ version: '5.2'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: httpclient
55
55
  requirement: !ruby/object:Gem::Requirement