telegram-bot-ruby 1.0.0 → 2.1.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 (210) 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 +16 -0
  9. data/Gemfile +11 -3
  10. data/LICENSE +0 -1
  11. data/README.md +64 -20
  12. data/Rakefile +0 -43
  13. data/bin/console +4 -1
  14. data/lib/telegram/bot/api/endpoints.rb +124 -0
  15. data/lib/telegram/bot/api.rb +20 -44
  16. data/lib/telegram/bot/client.rb +9 -10
  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/background_fill.rb +16 -0
  21. data/lib/telegram/bot/types/background_fill_freeform_gradient.rb +12 -0
  22. data/lib/telegram/bot/types/background_fill_gradient.rb +14 -0
  23. data/lib/telegram/bot/types/background_fill_solid.rb +12 -0
  24. data/lib/telegram/bot/types/background_type.rb +17 -0
  25. data/lib/telegram/bot/types/background_type_chat_theme.rb +12 -0
  26. data/lib/telegram/bot/types/background_type_fill.rb +13 -0
  27. data/lib/telegram/bot/types/background_type_pattern.rb +16 -0
  28. data/lib/telegram/bot/types/background_type_wallpaper.rb +15 -0
  29. data/lib/telegram/bot/types/birthdate.rb +13 -0
  30. data/lib/telegram/bot/types/bot_command.rb +2 -2
  31. data/lib/telegram/bot/types/bot_command_scope.rb +20 -0
  32. data/lib/telegram/bot/types/bot_command_scope_all_chat_administrators.rb +1 -1
  33. data/lib/telegram/bot/types/bot_command_scope_all_group_chats.rb +1 -1
  34. data/lib/telegram/bot/types/bot_command_scope_all_private_chats.rb +1 -1
  35. data/lib/telegram/bot/types/bot_command_scope_chat.rb +2 -2
  36. data/lib/telegram/bot/types/bot_command_scope_chat_administrators.rb +2 -2
  37. data/lib/telegram/bot/types/bot_command_scope_chat_member.rb +2 -2
  38. data/lib/telegram/bot/types/bot_command_scope_default.rb +1 -1
  39. data/lib/telegram/bot/types/bot_description.rb +11 -0
  40. data/lib/telegram/bot/types/bot_name.rb +11 -0
  41. data/lib/telegram/bot/types/bot_short_description.rb +11 -0
  42. data/lib/telegram/bot/types/business_connection.rb +16 -0
  43. data/lib/telegram/bot/types/business_intro.rb +13 -0
  44. data/lib/telegram/bot/types/business_location.rb +12 -0
  45. data/lib/telegram/bot/types/business_messages_deleted.rb +13 -0
  46. data/lib/telegram/bot/types/business_opening_hours.rb +12 -0
  47. data/lib/telegram/bot/types/business_opening_hours_interval.rb +12 -0
  48. data/lib/telegram/bot/types/callback_query.rb +1 -1
  49. data/lib/telegram/bot/types/chat.rb +1 -22
  50. data/lib/telegram/bot/types/chat_administrator_rights.rb +3 -0
  51. data/lib/telegram/bot/types/chat_background.rb +11 -0
  52. data/lib/telegram/bot/types/chat_boost.rb +14 -0
  53. data/lib/telegram/bot/types/chat_boost_added.rb +11 -0
  54. data/lib/telegram/bot/types/chat_boost_removed.rb +14 -0
  55. data/lib/telegram/bot/types/chat_boost_source.rb +16 -0
  56. data/lib/telegram/bot/types/chat_boost_source_gift_code.rb +12 -0
  57. data/lib/telegram/bot/types/chat_boost_source_giveaway.rb +15 -0
  58. data/lib/telegram/bot/types/chat_boost_source_premium.rb +12 -0
  59. data/lib/telegram/bot/types/chat_boost_updated.rb +12 -0
  60. data/lib/telegram/bot/types/chat_full_info.rb +54 -0
  61. data/lib/telegram/bot/types/chat_invite_link.rb +2 -0
  62. data/lib/telegram/bot/types/chat_location.rb +1 -1
  63. data/lib/telegram/bot/types/chat_member.rb +11 -2
  64. data/lib/telegram/bot/types/chat_member_administrator.rb +8 -5
  65. data/lib/telegram/bot/types/chat_member_banned.rb +2 -2
  66. data/lib/telegram/bot/types/chat_member_left.rb +2 -2
  67. data/lib/telegram/bot/types/chat_member_member.rb +3 -2
  68. data/lib/telegram/bot/types/chat_member_owner.rb +2 -2
  69. data/lib/telegram/bot/types/chat_member_restricted.rb +2 -2
  70. data/lib/telegram/bot/types/chat_member_updated.rb +2 -0
  71. data/lib/telegram/bot/types/chat_shared.rb +3 -0
  72. data/lib/telegram/bot/types/compactable.rb +2 -7
  73. data/lib/telegram/bot/types/copy_text_button.rb +11 -0
  74. data/lib/telegram/bot/types/document.rb +1 -1
  75. data/lib/telegram/bot/types/error.rb +14 -0
  76. data/lib/telegram/bot/types/external_reply_info.rb +34 -0
  77. data/lib/telegram/bot/types/force_reply.rb +3 -3
  78. data/lib/telegram/bot/types/gift.rb +15 -0
  79. data/lib/telegram/bot/types/gifts.rb +11 -0
  80. data/lib/telegram/bot/types/giveaway.rb +19 -0
  81. data/lib/telegram/bot/types/giveaway_completed.rb +14 -0
  82. data/lib/telegram/bot/types/giveaway_created.rb +11 -0
  83. data/lib/telegram/bot/types/giveaway_winners.rb +22 -0
  84. data/lib/telegram/bot/types/inaccessible_message.rb +13 -0
  85. data/lib/telegram/bot/types/inline_keyboard_button.rb +2 -0
  86. data/lib/telegram/bot/types/inline_query_result.rb +33 -0
  87. data/lib/telegram/bot/types/inline_query_result_article.rb +4 -4
  88. data/lib/telegram/bot/types/inline_query_result_audio.rb +1 -1
  89. data/lib/telegram/bot/types/inline_query_result_cached_audio.rb +1 -1
  90. data/lib/telegram/bot/types/inline_query_result_cached_document.rb +1 -1
  91. data/lib/telegram/bot/types/inline_query_result_cached_gif.rb +2 -1
  92. data/lib/telegram/bot/types/inline_query_result_cached_mpeg4_gif.rb +2 -1
  93. data/lib/telegram/bot/types/inline_query_result_cached_photo.rb +2 -1
  94. data/lib/telegram/bot/types/inline_query_result_cached_sticker.rb +1 -1
  95. data/lib/telegram/bot/types/inline_query_result_cached_video.rb +2 -1
  96. data/lib/telegram/bot/types/inline_query_result_cached_voice.rb +1 -1
  97. data/lib/telegram/bot/types/inline_query_result_contact.rb +4 -4
  98. data/lib/telegram/bot/types/inline_query_result_document.rb +4 -4
  99. data/lib/telegram/bot/types/inline_query_result_game.rb +1 -1
  100. data/lib/telegram/bot/types/inline_query_result_gif.rb +4 -3
  101. data/lib/telegram/bot/types/inline_query_result_location.rb +4 -4
  102. data/lib/telegram/bot/types/inline_query_result_mpeg4_gif.rb +4 -3
  103. data/lib/telegram/bot/types/inline_query_result_photo.rb +3 -2
  104. data/lib/telegram/bot/types/inline_query_result_venue.rb +4 -4
  105. data/lib/telegram/bot/types/inline_query_result_video.rb +3 -2
  106. data/lib/telegram/bot/types/inline_query_result_voice.rb +1 -1
  107. data/lib/telegram/bot/types/inline_query_results_button.rb +13 -0
  108. data/lib/telegram/bot/types/input_contact_message_content.rb +1 -1
  109. data/lib/telegram/bot/types/input_invoice_message_content.rb +5 -5
  110. data/lib/telegram/bot/types/input_location_message_content.rb +1 -1
  111. data/lib/telegram/bot/types/input_media.rb +18 -0
  112. data/lib/telegram/bot/types/input_media_animation.rb +3 -2
  113. data/lib/telegram/bot/types/input_media_audio.rb +2 -2
  114. data/lib/telegram/bot/types/input_media_document.rb +2 -2
  115. data/lib/telegram/bot/types/input_media_photo.rb +2 -1
  116. data/lib/telegram/bot/types/input_media_video.rb +3 -2
  117. data/lib/telegram/bot/types/input_message_content.rb +10 -2
  118. data/lib/telegram/bot/types/input_paid_media.rb +15 -0
  119. data/lib/telegram/bot/types/input_paid_media_photo.rb +12 -0
  120. data/lib/telegram/bot/types/input_paid_media_video.rb +17 -0
  121. data/lib/telegram/bot/types/input_poll_option.rb +13 -0
  122. data/lib/telegram/bot/types/input_sticker.rb +15 -0
  123. data/lib/telegram/bot/types/input_text_message_content.rb +3 -3
  124. data/lib/telegram/bot/types/input_venue_message_content.rb +1 -1
  125. data/lib/telegram/bot/types/keyboard_button.rb +1 -1
  126. data/lib/telegram/bot/types/keyboard_button_request_chat.rb +3 -0
  127. data/lib/telegram/bot/types/keyboard_button_request_users.rb +17 -0
  128. data/lib/telegram/bot/types/link_preview_options.rb +15 -0
  129. data/lib/telegram/bot/types/location.rb +1 -1
  130. data/lib/telegram/bot/types/maybe_inaccessible_message.rb +15 -0
  131. data/lib/telegram/bot/types/menu_button.rb +16 -0
  132. data/lib/telegram/bot/types/menu_button_commands.rb +1 -1
  133. data/lib/telegram/bot/types/menu_button_default.rb +1 -1
  134. data/lib/telegram/bot/types/menu_button_web_app.rb +1 -1
  135. data/lib/telegram/bot/types/message.rb +30 -16
  136. data/lib/telegram/bot/types/message_id.rb +11 -0
  137. data/lib/telegram/bot/types/message_origin.rb +17 -0
  138. data/lib/telegram/bot/types/message_origin_channel.rb +15 -0
  139. data/lib/telegram/bot/types/message_origin_chat.rb +14 -0
  140. data/lib/telegram/bot/types/message_origin_hidden_user.rb +13 -0
  141. data/lib/telegram/bot/types/message_origin_user.rb +13 -0
  142. data/lib/telegram/bot/types/message_reaction_count_updated.rb +14 -0
  143. data/lib/telegram/bot/types/message_reaction_updated.rb +17 -0
  144. data/lib/telegram/bot/types/paid_media.rb +16 -0
  145. data/lib/telegram/bot/types/paid_media_info.rb +12 -0
  146. data/lib/telegram/bot/types/paid_media_photo.rb +12 -0
  147. data/lib/telegram/bot/types/paid_media_preview.rb +14 -0
  148. data/lib/telegram/bot/types/paid_media_purchased.rb +12 -0
  149. data/lib/telegram/bot/types/paid_media_video.rb +12 -0
  150. data/lib/telegram/bot/types/passport_element_error.rb +22 -0
  151. data/lib/telegram/bot/types/passport_element_error_data_field.rb +1 -1
  152. data/lib/telegram/bot/types/passport_element_error_file.rb +1 -1
  153. data/lib/telegram/bot/types/passport_element_error_files.rb +2 -2
  154. data/lib/telegram/bot/types/passport_element_error_front_side.rb +1 -1
  155. data/lib/telegram/bot/types/passport_element_error_reverse_side.rb +1 -1
  156. data/lib/telegram/bot/types/passport_element_error_selfie.rb +1 -1
  157. data/lib/telegram/bot/types/passport_element_error_translation_file.rb +1 -1
  158. data/lib/telegram/bot/types/passport_element_error_translation_files.rb +2 -2
  159. data/lib/telegram/bot/types/passport_element_error_unspecified.rb +1 -1
  160. data/lib/telegram/bot/types/poll.rb +2 -1
  161. data/lib/telegram/bot/types/poll_answer.rb +2 -1
  162. data/lib/telegram/bot/types/poll_option.rb +2 -1
  163. data/lib/telegram/bot/types/prepared_inline_message.rb +12 -0
  164. data/lib/telegram/bot/types/reaction_count.rb +12 -0
  165. data/lib/telegram/bot/types/reaction_type.rb +16 -0
  166. data/lib/telegram/bot/types/reaction_type_custom_emoji.rb +12 -0
  167. data/lib/telegram/bot/types/reaction_type_emoji.rb +12 -0
  168. data/lib/telegram/bot/types/reaction_type_paid.rb +11 -0
  169. data/lib/telegram/bot/types/refunded_payment.rb +15 -0
  170. data/lib/telegram/bot/types/reply_keyboard_markup.rb +2 -2
  171. data/lib/telegram/bot/types/reply_keyboard_remove.rb +2 -2
  172. data/lib/telegram/bot/types/reply_parameters.rb +17 -0
  173. data/lib/telegram/bot/types/response_parameters.rb +12 -0
  174. data/lib/telegram/bot/types/revenue_withdrawal_state.rb +16 -0
  175. data/lib/telegram/bot/types/revenue_withdrawal_state_failed.rb +11 -0
  176. data/lib/telegram/bot/types/revenue_withdrawal_state_pending.rb +11 -0
  177. data/lib/telegram/bot/types/revenue_withdrawal_state_succeeded.rb +13 -0
  178. data/lib/telegram/bot/types/shared_user.rb +15 -0
  179. data/lib/telegram/bot/types/star_transaction.rb +15 -0
  180. data/lib/telegram/bot/types/star_transactions.rb +11 -0
  181. data/lib/telegram/bot/types/sticker.rb +2 -1
  182. data/lib/telegram/bot/types/sticker_set.rb +1 -3
  183. data/lib/telegram/bot/types/story.rb +12 -0
  184. data/lib/telegram/bot/types/successful_payment.rb +3 -0
  185. data/lib/telegram/bot/types/switch_inline_query_chosen_chat.rb +15 -0
  186. data/lib/telegram/bot/types/text_quote.rb +14 -0
  187. data/lib/telegram/bot/types/transaction_partner.rb +18 -0
  188. data/lib/telegram/bot/types/transaction_partner_fragment.rb +12 -0
  189. data/lib/telegram/bot/types/transaction_partner_other.rb +11 -0
  190. data/lib/telegram/bot/types/transaction_partner_telegram_ads.rb +11 -0
  191. data/lib/telegram/bot/types/transaction_partner_telegram_api.rb +12 -0
  192. data/lib/telegram/bot/types/transaction_partner_user.rb +17 -0
  193. data/lib/telegram/bot/types/update.rb +9 -0
  194. data/lib/telegram/bot/types/user.rb +4 -2
  195. data/lib/telegram/bot/types/user_chat_boosts.rb +11 -0
  196. data/lib/telegram/bot/types/{user_shared.rb → users_shared.rb} +2 -2
  197. data/lib/telegram/bot/types/video.rb +1 -1
  198. data/lib/telegram/bot/types/video_note.rb +1 -1
  199. data/lib/telegram/bot/types/webhook_info.rb +1 -1
  200. data/lib/telegram/bot/types/write_access_allowed.rb +3 -0
  201. data/lib/telegram/bot/version.rb +1 -1
  202. data/lib/telegram/bot.rb +1 -0
  203. data/rakelib/parse_schema.rake +73 -0
  204. data/rakelib/rebuild_types.rake +90 -0
  205. data/telegram-bot-ruby.gemspec +1 -4
  206. data/utility/empty_type.erb +14 -0
  207. data/utility/type.erb +13 -0
  208. data/utility/type_attributes.json +5138 -0
  209. metadata +105 -5
  210. data/lib/telegram/bot/types/keyboard_button_request_user.rb +0 -13
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class TextQuote < Base
7
+ attribute :text, Types::String
8
+ attribute? :entities, Types::Array.of(MessageEntity)
9
+ attribute :position, Types::Integer
10
+ attribute? :is_manual, Types::True
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ ## Just for classes consistency
7
+ # rubocop:disable Naming/ConstantName
8
+ TransactionPartner = (
9
+ TransactionPartnerUser |
10
+ TransactionPartnerFragment |
11
+ TransactionPartnerTelegramAds |
12
+ TransactionPartnerTelegramApi |
13
+ TransactionPartnerOther
14
+ )
15
+ # rubocop:enable Naming/ConstantName
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class TransactionPartnerFragment < Base
7
+ attribute :type, Types::String.constrained(eql: 'fragment').default('fragment')
8
+ attribute? :withdrawal_state, RevenueWithdrawalState
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class TransactionPartnerOther < Base
7
+ attribute :type, Types::String.constrained(eql: 'other').default('other')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class TransactionPartnerTelegramAds < Base
7
+ attribute :type, Types::String.constrained(eql: 'telegram_ads').default('telegram_ads')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class TransactionPartnerTelegramApi < Base
7
+ attribute :type, Types::String.constrained(eql: 'telegram_api').default('telegram_api')
8
+ attribute :request_count, Types::Integer
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class TransactionPartnerUser < Base
7
+ attribute :type, Types::String.constrained(eql: 'user').default('user')
8
+ attribute :user, User
9
+ attribute? :invoice_payload, Types::String
10
+ attribute? :subscription_period, Types::Integer
11
+ attribute? :paid_media, Types::Array.of(PaidMedia)
12
+ attribute? :paid_media_payload, Types::String
13
+ attribute? :gift, Gift
14
+ end
15
+ end
16
+ end
17
+ end
@@ -9,16 +9,25 @@ module Telegram
9
9
  attribute? :edited_message, Message
10
10
  attribute? :channel_post, Message
11
11
  attribute? :edited_channel_post, Message
12
+ attribute? :business_connection, BusinessConnection
13
+ attribute? :business_message, Message
14
+ attribute? :edited_business_message, Message
15
+ attribute? :deleted_business_messages, BusinessMessagesDeleted
16
+ attribute? :message_reaction, MessageReactionUpdated
17
+ attribute? :message_reaction_count, MessageReactionCountUpdated
12
18
  attribute? :inline_query, InlineQuery
13
19
  attribute? :chosen_inline_result, ChosenInlineResult
14
20
  attribute? :callback_query, CallbackQuery
15
21
  attribute? :shipping_query, ShippingQuery
16
22
  attribute? :pre_checkout_query, PreCheckoutQuery
23
+ attribute? :purchased_paid_media, PaidMediaPurchased
17
24
  attribute? :poll, Poll
18
25
  attribute? :poll_answer, PollAnswer
19
26
  attribute? :my_chat_member, ChatMemberUpdated
20
27
  attribute? :chat_member, ChatMemberUpdated
21
28
  attribute? :chat_join_request, ChatJoinRequest
29
+ attribute? :chat_boost, ChatBoostUpdated
30
+ attribute? :removed_chat_boost, ChatBoostRemoved
22
31
 
23
32
  def current_message
24
33
  @current_message ||=
@@ -10,11 +10,13 @@ module Telegram
10
10
  attribute? :last_name, Types::String
11
11
  attribute? :username, Types::String
12
12
  attribute? :language_code, Types::String
13
- attribute? :is_premium, Types::Bool
14
- attribute? :added_to_attachment_menu, Types::Bool
13
+ attribute? :is_premium, Types::True
14
+ attribute? :added_to_attachment_menu, Types::True
15
15
  attribute? :can_join_groups, Types::Bool
16
16
  attribute? :can_read_all_group_messages, Types::Bool
17
17
  attribute? :supports_inline_queries, Types::Bool
18
+ attribute? :can_connect_to_business, Types::Bool
19
+ attribute? :has_main_web_app, Types::Bool
18
20
  end
19
21
  end
20
22
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class UserChatBoosts < Base
7
+ attribute :boosts, Types::Array.of(ChatBoost)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,9 +3,9 @@
3
3
  module Telegram
4
4
  module Bot
5
5
  module Types
6
- class UserShared < Base
6
+ class UsersShared < Base
7
7
  attribute :request_id, Types::Integer
8
- attribute :user_id, Types::Integer
8
+ attribute :users, Types::Array.of(SharedUser)
9
9
  end
10
10
  end
11
11
  end
@@ -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
@@ -8,7 +8,7 @@ module Telegram
8
8
  attribute :file_unique_id, Types::String
9
9
  attribute :length, Types::Integer
10
10
  attribute :duration, Types::Integer
11
- attribute? :thumb, PhotoSize
11
+ attribute? :thumbnail, PhotoSize
12
12
  attribute? :file_size, Types::Integer
13
13
  end
14
14
  end
@@ -12,7 +12,7 @@ module Telegram
12
12
  attribute? :last_error_message, Types::String
13
13
  attribute? :last_synchronization_error_date, Types::Integer
14
14
  attribute? :max_connections, Types::Integer
15
- attribute? :allowed_updates, Types::Array.of(String)
15
+ attribute? :allowed_updates, Types::Array.of(Types::String)
16
16
  end
17
17
  end
18
18
  end
@@ -4,6 +4,9 @@ module Telegram
4
4
  module Bot
5
5
  module Types
6
6
  class WriteAccessAllowed < Base
7
+ attribute? :from_request, Types::Bool
8
+ attribute? :web_app_name, Types::String
9
+ attribute? :from_attachment_menu, Types::Bool
7
10
  end
8
11
  end
9
12
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Telegram
4
4
  module Bot
5
- VERSION = '1.0.0'
5
+ VERSION = '2.1.0'
6
6
  end
7
7
  end
data/lib/telegram/bot.rb CHANGED
@@ -25,5 +25,6 @@ end
25
25
 
26
26
  loader = Zeitwerk::Loader.new
27
27
  loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
28
+ loader.inflector.inflect('endpoints' => 'ENDPOINTS')
28
29
  loader.push_dir("#{__dir__}/bot", namespace: Telegram::Bot)
29
30
  loader.setup
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openapi3_parser'
4
+
5
+ desc 'Parse types from public json, should be up to date https://github.com/ark0f/tg-bot-api'
6
+ task :parse_schema do
7
+ document = Openapi3Parser.load_url('https://ark0f.github.io/tg-bot-api/openapi.json')
8
+
9
+ result = document.components.schemas.to_h do |type_name, schema|
10
+ type_schema = schema.properties.to_h do |property_name, property_schema|
11
+ attribute = { type: parse_initial_type(property_schema, property_name) }
12
+
13
+ unless property_schema.any_of.nil?
14
+ attribute[:type] = property_schema.any_of.map { |item| property_schema.name || item.name || item.type }.uniq
15
+ end
16
+
17
+ # Input File is literally just a string for our purpose
18
+ attribute[:type]&.delete('InputFile')
19
+ attribute[:type] = attribute[:type].join if attribute[:type]&.length == 1
20
+
21
+ attribute[:required] = true if required_keys(schema).include?(property_name)
22
+
23
+ # getting required values from the description, no values in json 😔
24
+ required_value = property_schema.description&.match(/always “(.+)”|must be \*(.+)\*/)
25
+ attribute[:required_value] = (required_value[1] || required_value[2]).delete('\\') if required_value
26
+
27
+ # for some reason every property's minLength is 0 by default, probably parser bug, had to ignore that
28
+ attribute[:min_size] = property_schema[:minLength] if property_schema[:minLength] != 0
29
+ attribute[:max_size] = property_schema[:maxLength] if property_schema[:maxLength]
30
+
31
+ attribute[:items] = property_schema.items.type if property_schema&.items
32
+ if property_schema&.type == 'array' && property_schema&.items&.type.nil?
33
+ attribute[:items] = property_schema&.items&.name
34
+ end
35
+
36
+ attribute[:items] = property_schema.items.name if property_schema&.items&.type == 'object'
37
+
38
+ # array of arrays
39
+ if property_schema&.items&.type == 'array'
40
+ attribute[:items] = { type: 'array', items: property_schema.items.items.name }
41
+ end
42
+
43
+ attribute = apply_default_schema(attribute, property_schema)
44
+ [property_name, attribute]
45
+ end
46
+
47
+ # find empty classes
48
+ type_schema[:type] = schema.any_of.map(&:name) if schema.properties.empty? && schema.any_of
49
+ [type_name, type_schema]
50
+ end
51
+
52
+ # Input File is literally just a string for our purpose
53
+ File.write "#{__dir__}/../utility/type_attributes.json", JSON.pretty_generate(result.except('InputFile'))
54
+ end
55
+
56
+ def required_keys(schema)
57
+ schema.required.to_a || []
58
+ end
59
+
60
+ def apply_default_schema(attribute, property_schema)
61
+ attribute[:default] = property_schema.default unless property_schema.default.nil?
62
+ # previous line would have been enough, but had to check the description due to issue: https://github.com/kevindew/openapi3_parser/issues/28
63
+ attribute[:default] = false if property_schema.description&.include?('Defaults to *false*')
64
+ attribute
65
+ end
66
+
67
+ def parse_initial_type(property_schema, property_name)
68
+ case property_schema.type
69
+ when nil then property_name.capitalize.gsub(/_(\w)/) { Regexp.last_match(1).upcase }
70
+ when 'object' then property_schema.name
71
+ else property_schema.type
72
+ end
73
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'erb'
5
+ DRY_TYPES = %w[string integer float decimal array hash symbol boolean date date_time time range].freeze
6
+
7
+ desc 'Rebuild types'
8
+ task :rebuild_types do
9
+ types = JSON.parse(File.read("#{__dir__}/../utility/type_attributes.json"), symbolize_names: true)
10
+
11
+ types.each_pair do |name, attributes|
12
+ next build_empty_type(name, attributes) if attributes[:type].instance_of?(Array)
13
+
14
+ attributes.each_pair do |attr_name, properties|
15
+ attributes[attr_name][:type] = add_module_types(properties[:type]) unless properties[:type].is_a?(Array)
16
+ if properties[:type].is_a?(Array)
17
+ attributes[attr_name][:type] = properties[:type].map do |type|
18
+ add_module_types(type)
19
+ end.join(' | ')
20
+ end
21
+
22
+ if properties[:items].instance_of?(String)
23
+ attributes[attr_name][:type] += ".of(#{add_module_types(properties[:items])})"
24
+ elsif properties[:items] && properties[:items][:type] == 'array'
25
+ attributes[attr_name][:type] += ".of(Types::Array.of(#{properties[:items][:items]}))"
26
+ end
27
+ original_type = properties[:type]
28
+
29
+ attributes = apply_required(attributes, attr_name, properties, original_type)
30
+ attributes = apply_min_max(attributes, attr_name, properties)
31
+ attributes = apply_default(attributes, attr_name, properties, original_type)
32
+
33
+ attributes[attr_name][:type] = 'Types::True' if attributes[attr_name][:type] == 'Types::Boolean.default(true)'
34
+ attributes[attr_name][:type] = attributes[attr_name][:type].gsub('Types::Boolean', 'Types::Bool')
35
+ end
36
+
37
+ File.write "#{__dir__}/../lib/telegram/bot/types/#{underscore(name)}.rb",
38
+ ERB.new(File.read("#{__dir__}/../utility/type.erb")).result(binding).gsub(" \n", '')
39
+ end
40
+ end
41
+
42
+ def build_empty_type(name, attributes)
43
+ attributes = attributes[:type].join(" |\n ")
44
+ File.write "#{__dir__}/../lib/telegram/bot/types/#{underscore(name)}.rb",
45
+ ERB.new(File.read("#{__dir__}/../utility/empty_type.erb")).result(binding).gsub(" \n", '')
46
+ end
47
+
48
+ def apply_default(attributes, attr_name, properties, original_type)
49
+ return attributes if properties[:default].nil?
50
+
51
+ attributes[attr_name][:type] += ".default(#{typecast(original_type,
52
+ properties[:default])})"
53
+ attributes
54
+ end
55
+
56
+ def apply_required(attributes, attr_name, properties, original_type)
57
+ return attributes unless properties[:required_value]
58
+
59
+ attributes[attr_name][:type] += ".constrained(eql: #{typecast(original_type,
60
+ properties[:required_value])})"
61
+ attributes
62
+ end
63
+
64
+ def apply_min_max(attributes, attr_name, properties)
65
+ return attributes unless properties[:min_size] || properties[:max_size]
66
+
67
+ constrain = '.constrained(minmax)'
68
+ constrain = properties[:min_size] ? constrain.gsub('min', "min_size: #{properties[:min_size]}, ") : ''
69
+ constrain = constrain.gsub('max', "max_size: #{properties[:max_size]}") if properties[:max_size]
70
+ attributes[attr_name][:type] += constrain
71
+ attributes
72
+ end
73
+
74
+ def add_module_types(type)
75
+ return 'Types::Float' if type == 'number'
76
+
77
+ DRY_TYPES.include?(type) ? "Types::#{type.capitalize}" : type
78
+ end
79
+
80
+ def underscore(camel_cased_word)
81
+ camel_cased_word.to_s.gsub('::', '/')
82
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
83
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
84
+ .tr('-', '_')
85
+ .downcase
86
+ end
87
+
88
+ def typecast(type, obj)
89
+ type == 'Types::String' ? "'#{obj}'" : obj
90
+ end
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
-
6
- require 'telegram/bot/version'
3
+ require_relative 'lib/telegram/bot/version'
7
4
 
8
5
  Gem::Specification.new do |spec|
9
6
  spec.name = 'telegram-bot-ruby'
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ ## Just for classes consistency
7
+ # rubocop:disable Naming/ConstantName
8
+ <%= name %> = (
9
+ <%= attributes %>
10
+ )
11
+ # rubocop:enable Naming/ConstantName
12
+ end
13
+ end
14
+ end
data/utility/type.erb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Telegram
4
+ module Bot
5
+ module Types
6
+ class <%= name %> < Base
7
+ <% attributes.each_pair do |name, properties| %>
8
+ <%= "#{properties[:required] ? 'attribute' : 'attribute?'} :#{name}, #{properties[:type]}" %>
9
+ <% end %>
10
+ end
11
+ end
12
+ end
13
+ end