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 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