telegram-bot-ruby 1.0.0 → 2.0.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.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +10 -0
  3. data/.github/workflows/ci.yml +0 -3
  4. data/.github/workflows/stale.yml +19 -0
  5. data/.gitignore +1 -0
  6. data/.rspec +1 -0
  7. data/.rubocop.yml +12 -7
  8. data/CHANGELOG.md +10 -0
  9. data/Gemfile +7 -3
  10. data/LICENSE +0 -1
  11. data/README.md +64 -20
  12. data/Rakefile +10 -8
  13. data/bin/console +4 -1
  14. data/lib/telegram/bot/api/endpoints.rb +114 -0
  15. data/lib/telegram/bot/api.rb +20 -44
  16. data/lib/telegram/bot/client.rb +8 -9
  17. data/lib/telegram/bot/exceptions/response_error.rb +2 -8
  18. data/lib/telegram/bot/types/animation.rb +1 -1
  19. data/lib/telegram/bot/types/audio.rb +1 -1
  20. data/lib/telegram/bot/types/bot_command_scope_all_chat_administrators.rb +1 -1
  21. data/lib/telegram/bot/types/bot_command_scope_all_group_chats.rb +1 -1
  22. data/lib/telegram/bot/types/bot_command_scope_all_private_chats.rb +1 -1
  23. data/lib/telegram/bot/types/bot_command_scope_chat.rb +2 -2
  24. data/lib/telegram/bot/types/bot_command_scope_chat_administrators.rb +2 -2
  25. data/lib/telegram/bot/types/bot_command_scope_chat_member.rb +2 -2
  26. data/lib/telegram/bot/types/bot_command_scope_default.rb +1 -1
  27. data/lib/telegram/bot/types/bot_description.rb +11 -0
  28. data/lib/telegram/bot/types/bot_name.rb +11 -0
  29. data/lib/telegram/bot/types/bot_short_description.rb +11 -0
  30. data/lib/telegram/bot/types/callback_query.rb +1 -1
  31. data/lib/telegram/bot/types/chat.rb +16 -9
  32. data/lib/telegram/bot/types/chat_administrator_rights.rb +3 -0
  33. data/lib/telegram/bot/types/chat_boost.rb +14 -0
  34. data/lib/telegram/bot/types/chat_boost_removed.rb +14 -0
  35. data/lib/telegram/bot/types/chat_boost_source.rb +13 -0
  36. data/lib/telegram/bot/types/chat_boost_source_gift_code.rb +12 -0
  37. data/lib/telegram/bot/types/chat_boost_source_giveaway.rb +14 -0
  38. data/lib/telegram/bot/types/chat_boost_source_premium.rb +12 -0
  39. data/lib/telegram/bot/types/chat_boost_updated.rb +12 -0
  40. data/lib/telegram/bot/types/chat_member.rb +11 -2
  41. data/lib/telegram/bot/types/chat_member_administrator.rb +8 -5
  42. data/lib/telegram/bot/types/chat_member_banned.rb +2 -2
  43. data/lib/telegram/bot/types/chat_member_left.rb +2 -2
  44. data/lib/telegram/bot/types/chat_member_member.rb +2 -2
  45. data/lib/telegram/bot/types/chat_member_owner.rb +2 -2
  46. data/lib/telegram/bot/types/chat_member_restricted.rb +2 -2
  47. data/lib/telegram/bot/types/chat_member_updated.rb +1 -0
  48. data/lib/telegram/bot/types/compactable.rb +2 -7
  49. data/lib/telegram/bot/types/document.rb +1 -1
  50. data/lib/telegram/bot/types/external_reply_info.rb +33 -0
  51. data/lib/telegram/bot/types/force_reply.rb +1 -1
  52. data/lib/telegram/bot/types/giveaway.rb +18 -0
  53. data/lib/telegram/bot/types/giveaway_completed.rb +13 -0
  54. data/lib/telegram/bot/types/giveaway_created.rb +10 -0
  55. data/lib/telegram/bot/types/giveaway_winners.rb +21 -0
  56. data/lib/telegram/bot/types/inaccessible_message.rb +13 -0
  57. data/lib/telegram/bot/types/inline_keyboard_button.rb +1 -0
  58. data/lib/telegram/bot/types/inline_query_result_article.rb +4 -4
  59. data/lib/telegram/bot/types/inline_query_result_audio.rb +1 -1
  60. data/lib/telegram/bot/types/inline_query_result_cached_audio.rb +1 -1
  61. data/lib/telegram/bot/types/inline_query_result_cached_document.rb +1 -1
  62. data/lib/telegram/bot/types/inline_query_result_cached_gif.rb +1 -1
  63. data/lib/telegram/bot/types/inline_query_result_cached_mpeg4_gif.rb +1 -1
  64. data/lib/telegram/bot/types/inline_query_result_cached_photo.rb +1 -1
  65. data/lib/telegram/bot/types/inline_query_result_cached_sticker.rb +1 -1
  66. data/lib/telegram/bot/types/inline_query_result_cached_video.rb +1 -1
  67. data/lib/telegram/bot/types/inline_query_result_cached_voice.rb +1 -1
  68. data/lib/telegram/bot/types/inline_query_result_contact.rb +4 -4
  69. data/lib/telegram/bot/types/inline_query_result_document.rb +4 -4
  70. data/lib/telegram/bot/types/inline_query_result_game.rb +1 -1
  71. data/lib/telegram/bot/types/inline_query_result_gif.rb +3 -3
  72. data/lib/telegram/bot/types/inline_query_result_location.rb +4 -4
  73. data/lib/telegram/bot/types/inline_query_result_mpeg4_gif.rb +3 -3
  74. data/lib/telegram/bot/types/inline_query_result_photo.rb +2 -2
  75. data/lib/telegram/bot/types/inline_query_result_venue.rb +4 -4
  76. data/lib/telegram/bot/types/inline_query_result_video.rb +2 -2
  77. data/lib/telegram/bot/types/inline_query_result_voice.rb +1 -1
  78. data/lib/telegram/bot/types/input_media_animation.rb +2 -2
  79. data/lib/telegram/bot/types/input_media_audio.rb +2 -2
  80. data/lib/telegram/bot/types/input_media_document.rb +2 -2
  81. data/lib/telegram/bot/types/input_media_photo.rb +1 -1
  82. data/lib/telegram/bot/types/input_media_video.rb +2 -2
  83. data/lib/telegram/bot/types/input_text_message_content.rb +1 -1
  84. data/lib/telegram/bot/types/keyboard_button.rb +1 -1
  85. data/lib/telegram/bot/types/{keyboard_button_request_user.rb → keyboard_button_request_users.rb} +2 -1
  86. data/lib/telegram/bot/types/link_preview_options.rb +15 -0
  87. data/lib/telegram/bot/types/maybe_inaccessible_message.rb +12 -0
  88. data/lib/telegram/bot/types/menu_button_commands.rb +1 -1
  89. data/lib/telegram/bot/types/menu_button_default.rb +1 -1
  90. data/lib/telegram/bot/types/menu_button_web_app.rb +1 -1
  91. data/lib/telegram/bot/types/message.rb +19 -16
  92. data/lib/telegram/bot/types/message_id.rb +11 -0
  93. data/lib/telegram/bot/types/message_origin.rb +14 -0
  94. data/lib/telegram/bot/types/message_origin_channel.rb +15 -0
  95. data/lib/telegram/bot/types/message_origin_chat.rb +14 -0
  96. data/lib/telegram/bot/types/message_origin_hidden_user.rb +13 -0
  97. data/lib/telegram/bot/types/message_origin_user.rb +13 -0
  98. data/lib/telegram/bot/types/message_reaction_count_updated.rb +14 -0
  99. data/lib/telegram/bot/types/message_reaction_updated.rb +17 -0
  100. data/lib/telegram/bot/types/passport_element_error_data_field.rb +1 -1
  101. data/lib/telegram/bot/types/passport_element_error_file.rb +1 -1
  102. data/lib/telegram/bot/types/passport_element_error_files.rb +2 -2
  103. data/lib/telegram/bot/types/passport_element_error_front_side.rb +1 -1
  104. data/lib/telegram/bot/types/passport_element_error_reverse_side.rb +1 -1
  105. data/lib/telegram/bot/types/passport_element_error_selfie.rb +1 -1
  106. data/lib/telegram/bot/types/passport_element_error_translation_file.rb +1 -1
  107. data/lib/telegram/bot/types/passport_element_error_translation_files.rb +2 -2
  108. data/lib/telegram/bot/types/passport_element_error_unspecified.rb +1 -1
  109. data/lib/telegram/bot/types/poll_answer.rb +2 -1
  110. data/lib/telegram/bot/types/reaction_count.rb +12 -0
  111. data/lib/telegram/bot/types/reaction_type.rb +12 -0
  112. data/lib/telegram/bot/types/reaction_type_custom_emoji.rb +12 -0
  113. data/lib/telegram/bot/types/reaction_type_emoji.rb +12 -0
  114. data/lib/telegram/bot/types/reply_keyboard_remove.rb +1 -1
  115. data/lib/telegram/bot/types/reply_parameters.rb +17 -0
  116. data/lib/telegram/bot/types/sticker.rb +2 -1
  117. data/lib/telegram/bot/types/sticker_set.rb +1 -1
  118. data/lib/telegram/bot/types/story.rb +9 -0
  119. data/lib/telegram/bot/types/switch_inline_query_chosen_chat.rb +15 -0
  120. data/lib/telegram/bot/types/text_quote.rb +14 -0
  121. data/lib/telegram/bot/types/update.rb +4 -0
  122. data/lib/telegram/bot/types/user.rb +2 -2
  123. data/lib/telegram/bot/types/user_chat_boosts.rb +11 -0
  124. data/lib/telegram/bot/types/{user_shared.rb → users_shared.rb} +2 -2
  125. data/lib/telegram/bot/types/video.rb +1 -1
  126. data/lib/telegram/bot/types/video_note.rb +1 -1
  127. data/lib/telegram/bot/types/webhook_info.rb +1 -1
  128. data/lib/telegram/bot/types/write_access_allowed.rb +3 -0
  129. data/lib/telegram/bot/version.rb +1 -1
  130. data/lib/telegram/bot.rb +1 -0
  131. data/telegram-bot-ruby.gemspec +1 -4
  132. metadata +43 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 849ef276ecc1cfd4531ccd49474ca72e21e6a737f4ee49af374fd0f2cb7a6368
4
- data.tar.gz: 8d451387892328aff6a1205f0b31b9221a07319c0b8d927c655d40283d2efc09
3
+ metadata.gz: 5b61e5af1f53cd133496f945bc7642b2a79e12a1d2be92faca3e45246b51dba5
4
+ data.tar.gz: de0024292072dfa7dcc74ffa6c66ba4e30d470652bcdcd5d9b193a8cea66f420
5
5
  SHA512:
6
- metadata.gz: ef343c2f15ee929777e6f03b5cc2e9af8f593e49a15bb751301476996bff8bcc3c79b99c962c5e865a379f23ddf8d505b0fabe22a3033a6e950a703ea54a9fa3
7
- data.tar.gz: a9add629f338919e2584cccb8c7b206eaef726df39021ac0f9b42e26e7cf2c1cb65a28735e0010c3f390aee0f90f29fcb3a5d2c1981f0b8ba4829d55b14fd421
6
+ metadata.gz: dab03a9d65d7582dce03bb6f5a8aea981a507f8011e2e618264177182c132c4fda82d1fc80da0590d3196e07e145e586c665af1fa8e9fd5fdfbcd8c36439bad2
7
+ data.tar.gz: 1b165086c50ee02e77298c575712551462c58bdb3f963a70ab823d2c9cffffdf23551af8caa3ad484e47bca3d89505f5656ae05c15648b37e6e84cc73e308011
data/.editorconfig ADDED
@@ -0,0 +1,10 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_size = 2
7
+ indent_style = space
8
+ insert_final_newline = true
9
+ max_line_length = 120
10
+ trim_trailing_whitespace = true
@@ -32,9 +32,6 @@ jobs:
32
32
  ruby:
33
33
  - 2.7
34
34
  - 3.2
35
- env:
36
- BOT_API_ENV: test
37
- BOT_API_TOKEN: ${{ secrets.BOT_API_TOKEN }}
38
35
  steps:
39
36
  - name: Checkout
40
37
  uses: actions/checkout@v3
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: Close stale issues and PRs
3
+ on:
4
+ schedule:
5
+ - cron: 40 * * * *
6
+
7
+ jobs:
8
+ stale:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/stale@v7
12
+ with:
13
+ days-before-close: 7
14
+ days-before-stale: 60
15
+ stale-issue-label: stale
16
+ stale-issue-message: This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.
17
+ stale-pr-label: stale
18
+ stale-pr-message: This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.
19
+ operations-per-run: 500
data/.gitignore CHANGED
@@ -3,4 +3,5 @@ Gemfile.lock
3
3
  .bundle/
4
4
  .env
5
5
  pkg/
6
+ tmp/
6
7
  vendor/bundle/
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --require spec_helper
2
2
  --color
3
+ --warnings
data/.rubocop.yml CHANGED
@@ -2,6 +2,7 @@
2
2
  require:
3
3
  - rubocop-rake
4
4
  - rubocop-rspec
5
+ - rubocop-performance
5
6
 
6
7
  AllCops:
7
8
  NewCops: enable
@@ -10,18 +11,22 @@ AllCops:
10
11
  Style/Documentation:
11
12
  Enabled: false
12
13
 
13
- Style/FrozenStringLiteralComment:
14
- Exclude:
15
- - bin/console
16
-
17
14
  Metrics/BlockLength:
18
15
  AllowedMethods:
19
16
  - context
20
17
  - describe
21
18
  - task
19
+ Metrics/ClassLength:
20
+ Exclude:
21
+ - lib/telegram/bot/api/endpoints.rb
22
+ Metrics/MethodLength:
23
+ Exclude:
24
+ - spec/**/*
22
25
 
23
26
  Layout/LineLength:
24
27
  Max: 120
25
- Exclude:
26
- - telegram-bot-ruby.gemspec
27
- - examples/*.rb
28
+
29
+ RSpec/MultipleMemoizedHelpers:
30
+ Enabled: false
31
+ RSpec/NestedGroups:
32
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Added
6
+
7
+ - [Bot API 7.0](https://core.telegram.org/bots/api#december-29-2023)
8
+
9
+ ### Changed
10
+
11
+ - API method calls now return corresponding response objects ([#285](https://github.com/atipugin/telegram-bot-ruby/pull/285), thx [@AlexWayfer](https://github.com/AlexWayfer))
12
+
3
13
  ## 1.0.0
4
14
 
5
15
  - Replace [virtus](https://github.com/solnic/virtus) with [dry-struct](https://github.com/dry-rb/dry-struct)
data/Gemfile CHANGED
@@ -8,7 +8,11 @@ gem 'dotenv', '~> 2.8'
8
8
  gem 'nokogiri', '~> 1.13'
9
9
  gem 'pry'
10
10
  gem 'rake', '~> 13.0'
11
+
11
12
  gem 'rspec', '~> 3.4'
12
- gem 'rubocop', '~> 1.27'
13
- gem 'rubocop-rake'
14
- gem 'rubocop-rspec', '~> 2.10'
13
+ gem 'vcr', '~> 6.0'
14
+
15
+ gem 'rubocop', '~> 1.54.1'
16
+ gem 'rubocop-performance', '~> 1.18'
17
+ gem 'rubocop-rake', '~> 0.6.0'
18
+ gem 'rubocop-rspec', '~> 2.22.0'
data/LICENSE CHANGED
@@ -11,4 +11,3 @@
11
11
  TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12
12
 
13
13
  0. You just DO WHAT THE FUCK YOU WANT TO.
14
-
data/README.md CHANGED
@@ -9,7 +9,9 @@ Ruby wrapper for [Telegram's Bot API](https://core.telegram.org/bots/api).
9
9
 
10
10
  ## 🚧 Upgrading to 1.0
11
11
 
12
- Since v1.0 telegram-bot-ruby uses [dry-struct](https://github.com/dry-rb/dry-struct) instead of [virtus](https://github.com/solnic/virtus). This means that type objects are now immutable and you can't change them after initialization:
12
+ Since v1.0 `telegram-bot-ruby` uses [`dry-struct`](https://github.com/dry-rb/dry-struct)
13
+ instead of [`virtus`](https://github.com/solnic/virtus).
14
+ This means that type objects are now immutable and you can't change them after initialization:
13
15
 
14
16
  ```ruby
15
17
  # This won't work
@@ -27,7 +29,7 @@ Please make sure it doesn't break your existing code before upgrading to 1.0.
27
29
  Add following line to your Gemfile:
28
30
 
29
31
  ```ruby
30
- gem 'telegram-bot-ruby'
32
+ gem 'telegram-bot-ruby', '~> 1.0'
31
33
  ```
32
34
 
33
35
  And then execute:
@@ -44,7 +46,8 @@ gem install telegram-bot-ruby
44
46
 
45
47
  ## Usage
46
48
 
47
- First things first, you need to [obtain a token](https://core.telegram.org/bots#6-botfather) for your bot. Then create your Telegram bot like this:
49
+ First things first, you need to [obtain a token](https://core.telegram.org/bots#6-botfather) for your bot.
50
+ Then create your Telegram bot like this:
48
51
 
49
52
  ```ruby
50
53
  require 'telegram/bot'
@@ -63,7 +66,10 @@ Telegram::Bot::Client.run(token) do |bot|
63
66
  end
64
67
  ```
65
68
 
66
- Note that `bot.api` object implements [Telegram Bot API methods](https://core.telegram.org/bots/api#available-methods) as is. So you can invoke any method inside the block without any problems. All methods are available in both *snake_case* and *camelCase* notations.
69
+ Note that `bot.api` object implements
70
+ [Telegram Bot API methods](https://core.telegram.org/bots/api#available-methods) as is.
71
+ So you can invoke any method inside the block without any problems.
72
+ All methods are available in both *snake_case* and *camelCase* notations.
67
73
 
68
74
  If you need to start a bot in development mode you have to pass `environment: :test`:
69
75
 
@@ -73,15 +79,35 @@ Telegram::Bot::Client.run(token, environment: :test) do |bot|
73
79
  end
74
80
  ```
75
81
 
76
- Same thing about `message` object - it implements [Message](https://core.telegram.org/bots/api#message) spec, so you always know what to expect from it.
82
+ Same thing about `message` object: it implements [Message](https://core.telegram.org/bots/api#message) spec,
83
+ so you always know what to expect from it.
84
+
85
+ To gracefully stop the bot, for example by `INT` signal (Ctrl-C), call the `bot.stop` method:
86
+
87
+ ```ruby
88
+ bot = Telegram::Bot::Client.new(token)
89
+
90
+ Signal.trap('INT') do
91
+ bot.stop
92
+ end
93
+
94
+ bot.listen do |message|
95
+ # it will be in an infinity loop until `bot.stop` command
96
+ # (with a small delay for the current `fetch_updates` request)
97
+ end
98
+ ```
77
99
 
78
100
  ## Webhooks
79
101
 
80
- If you are going to use [webhooks](https://core.telegram.org/bots/api#setwebhook) instead of [long polling](https://core.telegram.org/bots/api#getupdates), you need to implement your own webhook callbacks server. Take a look at [this repo](https://github.com/solyaris/BOTServer) as an example.
102
+ If you are going to use [webhooks](https://core.telegram.org/bots/api#setwebhook)
103
+ instead of [long polling](https://core.telegram.org/bots/api#getupdates),
104
+ you need to implement your own webhook callbacks server.
105
+ Take a look at [this repo](https://github.com/solyaris/BOTServer) as an example.
81
106
 
82
107
  ## Proxy
83
108
 
84
- As some countries block access to Telegram, you can set up your own proxy and use it to access Telegram API. In this case you need to configure API url:
109
+ As some countries block access to Telegram, you can set up your own proxy and use it to access Telegram API.
110
+ In this case you need to configure API URL:
85
111
 
86
112
  ```ruby
87
113
  Telegram::Bot::Client.run(token, url: 'https://proxy.example.com') do |bot|
@@ -91,7 +117,8 @@ end
91
117
 
92
118
  ## Custom keyboards
93
119
 
94
- You can use your own [custom keyboards](https://core.telegram.org/bots#keyboards). Here is an example:
120
+ You can use your own [custom keyboards](https://core.telegram.org/bots#keyboards).
121
+ Here is an example:
95
122
 
96
123
  ```ruby
97
124
  bot.listen do |message|
@@ -131,7 +158,8 @@ end
131
158
 
132
159
  ## Inline keyboards
133
160
 
134
- [Bot API 2.0](https://core.telegram.org/bots/2-0-intro) brought us new inline keyboards. Example:
161
+ [Bot API 2.0](https://core.telegram.org/bots/2-0-intro) brought us new inline keyboards.
162
+ Example:
135
163
 
136
164
  ```ruby
137
165
  bot.listen do |message|
@@ -179,13 +207,25 @@ bot.listen do |message|
179
207
  end
180
208
  ```
181
209
 
182
- Now, with `inline` mode enabled, your `message` object can be an instance of [Message](https://core.telegram.org/bots/api#message), [InlineQuery](https://core.telegram.org/bots/api#inlinequery) or [ChosenInlineResult](https://core.telegram.org/bots/api#choseninlineresult). That's why you need to check type of each message and decide how to handle it.
210
+ Now, with `inline` mode enabled, your `message` object can be an instance of
211
+ [Message](https://core.telegram.org/bots/api#message),
212
+ [InlineQuery](https://core.telegram.org/bots/api#inlinequery) or
213
+ [ChosenInlineResult](https://core.telegram.org/bots/api#choseninlineresult).
214
+ That's why you need to check type of each message and decide how to handle it.
183
215
 
184
- Using `answer_inline_query` you can send query results to user. `results` field must be an array of [query result objects](https://core.telegram.org/bots/api#inlinequeryresult).
216
+ Using `answer_inline_query` you can send query results to user.
217
+ `results` field must be an array of [query result objects](https://core.telegram.org/bots/api#inlinequeryresult).
185
218
 
186
219
  ## File upload
187
220
 
188
- Your bot can even upload files ([photos](https://core.telegram.org/bots/api#sendphoto), [audio](https://core.telegram.org/bots/api#sendaudio), [documents](https://core.telegram.org/bots/api#senddocument), [stickers](https://core.telegram.org/bots/api#sendsticker), [video](https://core.telegram.org/bots/api#sendvideo)) to Telegram servers. Just like this:
221
+ Your bot can even upload files
222
+ ([photos](https://core.telegram.org/bots/api#sendphoto),
223
+ [audio](https://core.telegram.org/bots/api#sendaudio),
224
+ [documents](https://core.telegram.org/bots/api#senddocument),
225
+ [stickers](https://core.telegram.org/bots/api#sendsticker),
226
+ [video](https://core.telegram.org/bots/api#sendvideo))
227
+ to Telegram servers.
228
+ Just like this:
189
229
 
190
230
  ```ruby
191
231
  bot.listen do |message|
@@ -199,7 +239,9 @@ end
199
239
 
200
240
  ## Logging
201
241
 
202
- By default, bot doesn't log anything (uses `NullLoger`). You can change this behavior and provide your own logger class. See example below:
242
+ By default, bot doesn't log anything (uses `NullLoger`).
243
+ You can change this behavior and provide your own logger class.
244
+ See example below:
203
245
 
204
246
  ```ruby
205
247
  Telegram::Bot::Client.run(token, logger: Logger.new($stderr)) do |bot|
@@ -212,7 +254,8 @@ end
212
254
 
213
255
  ## Connection adapters
214
256
 
215
- Since version `0.5.0` we rely on [faraday](https://github.com/lostisland/faraday) under the hood. You can use any of supported adapters (for example, `net/http/persistent`):
257
+ Since version `0.5.0` we rely on [faraday](https://github.com/lostisland/faraday) under the hood.
258
+ You can use any of supported adapters (for example, `net/http/persistent`):
216
259
 
217
260
  ```ruby
218
261
  require 'net/http/persistent'
@@ -224,14 +267,15 @@ end
224
267
 
225
268
  ## Boilerplates
226
269
 
227
- If you don't know how to setup database for your bot or how to use it with different languages here are some boilerplates which can help you to start faster:
270
+ If you don't know how to setup database for your bot or how to use it with different languages
271
+ here are some boilerplates which can help you to start faster:
228
272
 
229
273
  - [Ruby Telegram Bot boilerplate](https://github.com/telegram-bots/ruby-telegram-bot-boilerplate)
230
274
 
231
275
  ## Contributing
232
276
 
233
- 1. Fork it
234
- 2. Create your feature branch (git checkout -b my-new-feature)
235
- 3. Commit your changes (git commit -am 'Add some feature')
236
- 4. Push to the branch (git push origin my-new-feature)
237
- 5. Create new Pull Request
277
+ 1. Fork it.
278
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
279
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
280
+ 4. Push to the branch (`git push origin my-new-feature`).
281
+ 5. Create a new Pull Request.
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ task default: :spec
18
18
 
19
19
  desc 'Dump type definitions from docs to YAML'
20
20
  task :dump_type_attributes do
21
- require File.expand_path('lib/telegram/bot', __dir__)
21
+ require_relative 'lib/telegram/bot'
22
22
  require 'nokogiri'
23
23
  require 'open-uri'
24
24
  require 'yaml'
@@ -30,6 +30,8 @@ task :dump_type_attributes do
30
30
  # Fetch and parse docs
31
31
  doc = Nokogiri::HTML(URI.open('https://core.telegram.org/bots/api').read)
32
32
 
33
+ next_type_element_names = %w[table h4]
34
+
33
35
  result = types.to_h do |type|
34
36
  # This is very hacky but working way to find table containing attributes for
35
37
  # given type. Basic idea is to find heading with type and then iterate until
@@ -38,23 +40,23 @@ task :dump_type_attributes do
38
40
  element = doc.at_xpath(%{//h4[text() = "#{type}"]})
39
41
  loop do
40
42
  element = element.next_element
41
- break if %w[table h4].include?(element.name)
43
+ break if next_type_element_names.include?(element.name)
42
44
  end
43
45
 
44
46
  attributes = element.xpath('.//tbody//tr').map do |el|
45
47
  cells = el.children.select { |c| c.name == 'td' }
46
48
  {
47
49
  'name' => cells[0].text,
48
- 'required' => !cells[2].text.start_with?('Optional.')
49
- }
50
+ 'type' => cells[1].text,
51
+ 'required' => !cells[2].text.start_with?('Optional.'),
52
+ 'required_value' =>
53
+ cells[2].text.match(/^.+, (?:must be (?<found_type>\w+)|always “(?<found_type>\w+)”)$/)&.[](:found_type)
54
+ }.compact
50
55
  end
51
56
 
52
57
  [type, attributes]
53
58
  end
54
59
 
55
60
  # Write everything to fixture file
56
- File.write(
57
- File.expand_path('spec/support/type_attributes.yml', __dir__),
58
- result.to_yaml
59
- )
61
+ File.write "#{__dir__}/spec/support/type_attributes.yml", result.to_yaml
60
62
  end
data/bin/console CHANGED
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
2
5
  require 'bundler/setup'
3
6
  require 'pry'
4
7
 
5
- require File.expand_path('../lib/telegram/bot', __dir__)
8
+ require_relative '../lib/telegram/bot'
6
9
 
7
10
  Pry.start
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ class Api
6
+ ENDPOINTS = {
7
+ 'getUpdates' => Types::Array.of(Types::Update),
8
+ 'setWebhook' => Types::Bool,
9
+ 'deleteWebhook' => Types::Bool,
10
+ 'getWebhookInfo' => Types::WebhookInfo,
11
+ 'getMe' => Types::User,
12
+ 'sendMessage' => Types::Message,
13
+ 'forwardMessage' => Types::Message,
14
+ 'forwardMessages' => Types::Array.of(Types::MessageId),
15
+ 'sendPhoto' => Types::Message,
16
+ 'sendAudio' => Types::Message,
17
+ 'sendDocument' => Types::Message,
18
+ 'sendVideo' => Types::Message,
19
+ 'sendVoice' => Types::Message,
20
+ 'sendVideoNote' => Types::Message,
21
+ 'sendMediaGroup' => Types::Array.of(Types::Message),
22
+ 'sendLocation' => Types::Message,
23
+ 'editMessageLiveLocation' => Types::Message | Types::Bool,
24
+ 'stopMessageLiveLocation' => Types::Message | Types::Bool,
25
+ 'sendVenue' => Types::Message,
26
+ 'sendContact' => Types::Message,
27
+ 'sendChatAction' => Types::Bool,
28
+ 'setMessageReaction' => Types::Bool,
29
+ 'getUserProfilePhotos' => Types::UserProfilePhotos,
30
+ 'getFile' => Types::File,
31
+ 'banChatMember' => Types::Bool,
32
+ 'unbanChatMember' => Types::Bool,
33
+ 'restrictChatMember' => Types::Bool,
34
+ 'promoteChatMember' => Types::Bool,
35
+ 'leaveChat' => Types::Bool,
36
+ 'getChat' => Types::Chat,
37
+ 'getChatAdministrators' => Types::Array.of(Types::ChatMember),
38
+ 'exportChatInviteLink' => Types::String,
39
+ 'setChatPhoto' => Types::Bool,
40
+ 'deleteChatPhoto' => Types::Bool,
41
+ 'setChatTitle' => Types::Bool,
42
+ 'setChatDescription' => Types::Bool,
43
+ 'pinChatMessage' => Types::Bool,
44
+ 'unpinChatMessage' => Types::Bool,
45
+ 'getChatMembersCount' => Types::Integer,
46
+ 'getChatMember' => Types::ChatMember,
47
+ 'setChatStickerSet' => Types::Bool,
48
+ 'deleteChatStickerSet' => Types::Bool,
49
+ 'answerCallbackQuery' => Types::Bool,
50
+ 'getUserChatBoosts' => Types::UserChatBoosts,
51
+ 'editMessageText' => Types::Message | Types::Bool,
52
+ 'editMessageCaption' => Types::Message | Types::Bool,
53
+ 'editMessageReplyMarkup' => Types::Message | Types::Bool,
54
+ 'deleteMessage' => Types::Bool,
55
+ 'deleteMessages' => Types::Bool,
56
+ 'sendSticker' => Types::Message,
57
+ 'getStickerSet' => Types::StickerSet,
58
+ 'uploadStickerFile' => Types::File,
59
+ 'createNewStickerSet' => Types::Bool,
60
+ 'addStickerToSet' => Types::Bool,
61
+ 'setStickerPositionInSet' => Types::Bool,
62
+ 'deleteStickerFromSet' => Types::Bool,
63
+ 'answerInlineQuery' => Types::Bool,
64
+ 'sendInvoice' => Types::Message,
65
+ 'answerShippingQuery' => Types::Bool,
66
+ 'answerPreCheckoutQuery' => Types::Bool,
67
+ 'sendGame' => Types::Message,
68
+ 'setGameScore' => Types::Message | Types::Bool,
69
+ 'getGameHighScores' => Types::Array.of(Types::GameHighScore),
70
+ 'setPassportDataErrors' => Types::Bool,
71
+ 'editMessageMedia' => Types::Message | Types::Bool,
72
+ 'sendAnimation' => Types::Message,
73
+ 'sendPoll' => Types::Message,
74
+ 'stopPoll' => Types::Poll,
75
+ 'setChatPermissions' => Types::Bool,
76
+ 'setChatAdministratorCustomTitle' => Types::Bool,
77
+ 'sendDice' => Types::Message,
78
+ 'getMyCommands' => Types::Array.of(Types::BotCommand),
79
+ 'setMyCommands' => Types::Bool,
80
+ 'deleteMyCommands' => Types::Bool,
81
+ 'setStickerSetThumbnail' => Types::Bool,
82
+ 'logOut' => Types::Bool,
83
+ 'close' => Types::Bool,
84
+ 'copyMessage' => Types::MessageId,
85
+ 'copyMessages' => Types::Array.of(Types::MessageId),
86
+ 'createChatInviteLink' => Types::ChatInviteLink,
87
+ 'editChatInviteLink' => Types::ChatInviteLink,
88
+ 'revokeChatInviteLink' => Types::ChatInviteLink,
89
+ 'approveChatJoinRequest' => Types::Bool,
90
+ 'declineChatJoinRequest' => Types::Bool,
91
+ 'banChatSenderChat' => Types::Bool,
92
+ 'unbanChatSenderChat' => Types::Bool,
93
+ 'answerWebAppQuery' => Types::SentWebAppMessage,
94
+ 'setChatMenuButton' => Types::Bool,
95
+ 'getChatMenuButton' => Types::MenuButtonDefault | Types::MenuButtonCommands | Types::MenuButtonWebApp,
96
+ 'setMyDefaultAdministratorRights' => Types::Bool,
97
+ 'getMyDefaultAdministratorRights' => Types::ChatAdministratorRights,
98
+ 'createInvoiceLink' => Types::String,
99
+ 'editGeneralForumTopic' => Types::Bool,
100
+ 'closeGeneralForumTopic' => Types::Bool,
101
+ 'reopenGeneralForumTopic' => Types::Bool,
102
+ 'hideGeneralForumTopic' => Types::Bool,
103
+ 'unhideGeneralForumTopic' => Types::Bool,
104
+ 'unpinAllGeneralForumTopicMessages' => Types::Bool,
105
+ 'setMyName' => Types::Bool,
106
+ 'getMyName' => Types::BotName,
107
+ 'setMyDescription' => Types::Bool,
108
+ 'getMyDescription' => Types::BotDescription,
109
+ 'setMyShortDescription' => Types::Bool,
110
+ 'getMyShortDescription' => Types::BotShortDescription
111
+ }.freeze
112
+ end
113
+ end
114
+ end
@@ -3,34 +3,6 @@
3
3
  module Telegram
4
4
  module Bot
5
5
  class Api
6
- ENDPOINTS = %w[
7
- getUpdates setWebhook deleteWebhook getWebhookInfo getMe sendMessage
8
- forwardMessage sendPhoto sendAudio sendDocument sendVideo sendVoice
9
- sendVideoNote sendMediaGroup sendLocation editMessageLiveLocation
10
- stopMessageLiveLocation sendVenue sendContact sendChatAction
11
- getUserProfilePhotos getFile kickChatMember unbanChatMember
12
- restrictChatMember promoteChatMember leaveChat getChat
13
- getChatAdministrators exportChatInviteLink setChatPhoto deleteChatPhoto
14
- setChatTitle setChatDescription pinChatMessage unpinChatMessage
15
- getChatMembersCount getChatMember setChatStickerSet deleteChatStickerSet
16
- answerCallbackQuery editMessageText editMessageCaption
17
- editMessageReplyMarkup deleteMessage sendSticker getStickerSet
18
- uploadStickerFile createNewStickerSet addStickerToSet
19
- setStickerPositionInSet deleteStickerFromSet answerInlineQuery
20
- sendInvoice answerShippingQuery answerPreCheckoutQuery
21
- sendGame setGameScore getGameHighScores setPassportDataErrors
22
- editMessageMedia sendAnimation sendPoll stopPoll setChatPermissions
23
- setChatAdministratorCustomTitle sendDice getMyCommands setMyCommands
24
- deleteMyCommands setStickerSetThumb logOut close copyMessage
25
- createChatInviteLink editChatInviteLink revokeChatInviteLink
26
- approveChatJoinRequest declineChatJoinRequest banChatSenderChat
27
- unbanChatSenderChat answerWebAppQuery setChatMenuButton
28
- getChatMenuButton setMyDefaultAdministratorRights
29
- getMyDefaultAdministratorRights createInvoiceLink editGeneralForumTopic
30
- closeGeneralForumTopic reopenGeneralForumTopic hideGeneralForumTopic
31
- unhideGeneralForumTopic
32
- ].freeze
33
-
34
6
  attr_reader :token, :url, :environment
35
7
 
36
8
  def initialize(token, url: 'https://api.telegram.org', environment: :production)
@@ -39,27 +11,41 @@ module Telegram
39
11
  @environment = environment.downcase.to_sym
40
12
  end
41
13
 
14
+ def connection
15
+ @connection ||= Faraday.new(url: url) do |faraday|
16
+ faraday.request :multipart
17
+ faraday.request :url_encoded
18
+ faraday.adapter Telegram::Bot.configuration.adapter
19
+ faraday.options.timeout = Telegram::Bot.configuration.connection_timeout
20
+ faraday.options.open_timeout = Telegram::Bot.configuration.connection_open_timeout
21
+ end
22
+ end
23
+
42
24
  def method_missing(method_name, *args, &block)
43
25
  endpoint = method_name.to_s
44
26
  endpoint = camelize(endpoint) if endpoint.include?('_')
45
27
 
46
- ENDPOINTS.include?(endpoint) ? call(endpoint, *args) : super
28
+ return super unless ENDPOINTS.key?(endpoint)
29
+
30
+ result = call(endpoint, *args)
31
+
32
+ return result['ok'] unless (result = result['result'])
33
+
34
+ ENDPOINTS[endpoint].call(result)
47
35
  end
48
36
 
49
37
  def respond_to_missing?(*args)
50
38
  method_name = args[0].to_s
51
39
  method_name = camelize(method_name) if method_name.include?('_')
52
40
 
53
- ENDPOINTS.include?(method_name) || super
41
+ ENDPOINTS.key?(method_name) || super
54
42
  end
55
43
 
56
44
  def call(endpoint, raw_params = {})
57
45
  params = build_params(raw_params)
58
46
  path = build_path(endpoint)
59
- response = conn.post(path, params)
60
- unless response.status == 200
61
- raise Exceptions::ResponseError.new(response), 'Telegram API has returned the error.'
62
- end
47
+ response = connection.post(path, params)
48
+ raise Exceptions::ResponseError.new(response: response) unless response.status == 200
63
49
 
64
50
  JSON.parse(response.body)
65
51
  end
@@ -95,16 +81,6 @@ module Telegram
95
81
  words.drop(1).map(&:capitalize!)
96
82
  words.join
97
83
  end
98
-
99
- def conn
100
- @conn ||= Faraday.new(url: url) do |faraday|
101
- faraday.request :multipart
102
- faraday.request :url_encoded
103
- faraday.adapter Telegram::Bot.configuration.adapter
104
- faraday.options.timeout = Telegram::Bot.configuration.connection_timeout
105
- faraday.options.open_timeout = Telegram::Bot.configuration.connection_open_timeout
106
- end
107
- end
108
84
  end
109
85
  end
110
86
  end
@@ -22,18 +22,17 @@ module Telegram
22
22
 
23
23
  def listen(&block)
24
24
  logger.info('Starting bot')
25
- running = true
26
- Signal.trap('INT') { running = false }
27
- fetch_updates(&block) while running
28
- exit
25
+ @running = true
26
+ fetch_updates(&block) while @running
29
27
  end
30
28
 
31
- def fetch_updates
32
- response = api.getUpdates(options)
33
- return unless response['ok']
29
+ def stop
30
+ @running = false
31
+ end
34
32
 
35
- response['result'].each do |data|
36
- yield handle_update(Types::Update.new(data))
33
+ def fetch_updates
34
+ api.getUpdates(options).each do |update|
35
+ yield handle_update(update)
37
36
  end
38
37
  rescue Faraday::TimeoutError, Faraday::ConnectionFailed
39
38
  retry
@@ -6,22 +6,16 @@ module Telegram
6
6
  class ResponseError < Base
7
7
  attr_reader :response
8
8
 
9
- def initialize(response)
9
+ def initialize(response:)
10
10
  @response = response
11
- super
12
- end
13
11
 
14
- def to_s
15
- super +
16
- format(' (%s)', data.map { |k, v| %(#{k}: "#{v}") }.join(', '))
12
+ super "Telegram API has returned the error. (#{data.map { |k, v| %(#{k}: #{v.inspect}) }.join(', ')})"
17
13
  end
18
14
 
19
15
  def error_code
20
16
  data[:error_code] || data['error_code']
21
17
  end
22
18
 
23
- private
24
-
25
19
  def data
26
20
  @data ||= begin
27
21
  JSON.parse(response.body)
@@ -9,7 +9,7 @@ module Telegram
9
9
  attribute :width, Types::Integer
10
10
  attribute :height, Types::Integer
11
11
  attribute :duration, Types::Integer
12
- attribute? :thumb, PhotoSize
12
+ attribute? :thumbnail, PhotoSize
13
13
  attribute? :file_name, Types::String
14
14
  attribute? :mime_type, Types::String
15
15
  attribute? :file_size, Types::Integer
@@ -12,7 +12,7 @@ module Telegram
12
12
  attribute? :file_name, Types::String
13
13
  attribute? :mime_type, Types::String
14
14
  attribute? :file_size, Types::Integer
15
- attribute? :thumb, PhotoSize
15
+ attribute? :thumbnail, PhotoSize
16
16
  end
17
17
  end
18
18
  end