gruubY 0.2.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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +6 -0
  4. data/Rakefile +51 -0
  5. data/config/config.rb +5 -0
  6. data/example/bot.rb +160 -0
  7. data/example/generate_user_session.rb +81 -0
  8. data/example/ntgcalls.rb +80 -0
  9. data/example/tdlib.rb +77 -0
  10. data/example/userbot.rb +133 -0
  11. data/lib/grubY/api.rb +363 -0
  12. data/lib/grubY/async.rb +13 -0
  13. data/lib/grubY/bot.rb +90 -0
  14. data/lib/grubY/bound.rb +14 -0
  15. data/lib/grubY/client.rb +296 -0
  16. data/lib/grubY/context.rb +242 -0
  17. data/lib/grubY/dispatcher.rb +60 -0
  18. data/lib/grubY/enums.rb +62 -0
  19. data/lib/grubY/exception.rb +5 -0
  20. data/lib/grubY/file_stream.rb +17 -0
  21. data/lib/grubY/filters.rb +292 -0
  22. data/lib/grubY/group_manager.rb +213 -0
  23. data/lib/grubY/handlers.rb +170 -0
  24. data/lib/grubY/keyboard.rb +49 -0
  25. data/lib/grubY/media.rb +38 -0
  26. data/lib/grubY/middleware.rb +18 -0
  27. data/lib/grubY/ntgcalls/native.rb +100 -0
  28. data/lib/grubY/ntgcalls.rb +478 -0
  29. data/lib/grubY/plugin.rb +14 -0
  30. data/lib/grubY/raw.rb +25 -0
  31. data/lib/grubY/raw_types.rb +57 -0
  32. data/lib/grubY/retry.rb +14 -0
  33. data/lib/grubY/server.rb +18 -0
  34. data/lib/grubY/session.rb +30 -0
  35. data/lib/grubY/tdlib/client.rb +565 -0
  36. data/lib/grubY/tdlib/client_manager.rb +37 -0
  37. data/lib/grubY/tdlib/decorators.rb +17 -0
  38. data/lib/grubY/tdlib/errors.rb +6 -0
  39. data/lib/grubY/tdlib/group_manager.rb +58 -0
  40. data/lib/grubY/tdlib/native.rb +72 -0
  41. data/lib/grubY/tdlib/schema_builder.rb +237 -0
  42. data/lib/grubY/tdlib/tdjson.rb +49 -0
  43. data/lib/grubY/tdlib/user_session.rb +69 -0
  44. data/lib/grubY/types/base_object.rb +72 -0
  45. data/lib/grubY/types/bound_entities.rb +245 -0
  46. data/lib/grubY/types/chat.rb +93 -0
  47. data/lib/grubY/types/chat_info.rb +31 -0
  48. data/lib/grubY/types/extra.rb +251 -0
  49. data/lib/grubY/types/message.rb +295 -0
  50. data/lib/grubY/types/message_entity.rb +14 -0
  51. data/lib/grubY/types/registry.rb +67 -0
  52. data/lib/grubY/types/user.rb +31 -0
  53. data/lib/grubY/webapp.rb +22 -0
  54. data/lib/grubY.rb +41 -0
  55. data/plugins/logger.rb +7 -0
  56. data/plugins/media_tools.rb +13 -0
  57. metadata +110 -0
@@ -0,0 +1,295 @@
1
+ require_relative "base_object"
2
+ require_relative "user"
3
+ require_relative "chat"
4
+ require_relative "message_entity"
5
+ require_relative "extra"
6
+
7
+ module GrubY
8
+ class Message < BaseObject
9
+ fields :message_id, :message_thread_id, :direct_messages_topic, :from,
10
+ :sender_chat, :sender_boost_count, :sender_business_bot, :sender_tag,
11
+ :date, :business_connection_id, :chat, :forward_origin, :is_topic_message,
12
+ :is_automatic_forward, :reply_to_message, :external_reply, :quote,
13
+ :reply_to_story, :reply_to_checklist_task_id, :reply_to_poll_option_id,
14
+ :via_bot, :edit_date, :has_protected_content, :is_from_offline,
15
+ :is_paid_post, :media_group_id, :author_signature, :paid_star_count,
16
+ :text, :entities, :link_preview_options, :suggested_post_info, :effect_id,
17
+ :animation, :audio, :document, :paid_media, :photo, :sticker, :story,
18
+ :video, :video_note, :voice, :caption, :caption_entities,
19
+ :show_caption_above_media, :has_media_spoiler, :checklist, :contact, :dice,
20
+ :game, :poll, :venue, :location, :new_chat_members, :left_chat_member,
21
+ :chat_owner_left, :chat_owner_changed, :new_chat_title, :new_chat_photo,
22
+ :delete_chat_photo, :group_chat_created, :supergroup_chat_created,
23
+ :channel_chat_created, :message_auto_delete_timer_changed,
24
+ :migrate_to_chat_id, :migrate_from_chat_id, :pinned_message, :invoice,
25
+ :successful_payment, :refunded_payment, :users_shared, :chat_shared, :gift,
26
+ :unique_gift, :gift_upgrade_sent, :connected_website,
27
+ :write_access_allowed, :passport_data, :proximity_alert_triggered,
28
+ :boost_added, :chat_background_set, :checklist_tasks_done,
29
+ :checklist_tasks_added, :direct_message_price_changed,
30
+ :forum_topic_created, :forum_topic_edited, :forum_topic_closed,
31
+ :forum_topic_reopened, :general_forum_topic_hidden,
32
+ :general_forum_topic_unhidden, :giveaway_created, :giveaway,
33
+ :giveaway_winners, :giveaway_completed, :managed_bot_created,
34
+ :paid_message_price_changed, :poll_option_added, :poll_option_deleted,
35
+ :suggested_post_approved, :suggested_post_approval_failed,
36
+ :suggested_post_declined, :suggested_post_paid,
37
+ :suggested_post_refunded, :video_chat_scheduled, :video_chat_started,
38
+ :video_chat_ended, :video_chat_participants_invited, :web_app_data,
39
+ :reply_markup
40
+
41
+ def initialize(data, api: nil, client: nil)
42
+ super(data, api: api, client: client)
43
+ @from = User.new(@from, api: api, client: client) if @from.is_a?(Hash)
44
+ @chat = Chat.new(@chat, api: api, client: client) if @chat.is_a?(Hash)
45
+ @sender_chat = Chat.new(@sender_chat, api: api, client: client) if @sender_chat.is_a?(Hash)
46
+ @sender_business_bot = User.new(@sender_business_bot, api: api, client: client) if @sender_business_bot.is_a?(Hash)
47
+ @via_bot = User.new(@via_bot, api: api, client: client) if @via_bot.is_a?(Hash)
48
+ @reply_to_message = Message.new(@reply_to_message, api: api, client: client) if @reply_to_message.is_a?(Hash)
49
+ @external_reply = ExternalReplyInfo.new(@external_reply) if @external_reply.is_a?(Hash)
50
+ @quote = TextQuote.new(@quote) if @quote.is_a?(Hash)
51
+ @reply_to_story = Story.new(@reply_to_story) if @reply_to_story.is_a?(Hash)
52
+ @entities = Array(@entities).map { |e| MessageEntity.new(e) }
53
+ @caption_entities = Array(@caption_entities).map { |e| MessageEntity.new(e) }
54
+ @photo = Array(@photo).map { |p| PhotoSize.new(p) }
55
+ @animation = Animation.new(@animation) if @animation.is_a?(Hash)
56
+ @audio = Audio.new(@audio) if @audio.is_a?(Hash)
57
+ @document = Document.new(@document) if @document.is_a?(Hash)
58
+ @story = Story.new(@story) if @story.is_a?(Hash)
59
+ @video = Video.new(@video) if @video.is_a?(Hash)
60
+ @video_note = VideoNote.new(@video_note) if @video_note.is_a?(Hash)
61
+ @voice = Voice.new(@voice) if @voice.is_a?(Hash)
62
+ @paid_media = PaidMediaInfo.new(@paid_media) if @paid_media.is_a?(Hash)
63
+ @contact = Contact.new(@contact) if @contact.is_a?(Hash)
64
+ @dice = Dice.new(@dice) if @dice.is_a?(Hash)
65
+ @poll = Poll.new(@poll) if @poll.is_a?(Hash)
66
+ @new_chat_members = Array(@new_chat_members).map { |u| User.new(u, api: api, client: client) }
67
+ @left_chat_member = User.new(@left_chat_member, api: api, client: client) if @left_chat_member.is_a?(Hash)
68
+ end
69
+
70
+ def reply(text = nil, **opts)
71
+ call_api("sendMessage", { chat_id: chat_id!, text: text.to_s, reply_to_message_id: message_id }.merge(opts))
72
+ end
73
+
74
+ def reply_text(text = nil, **opts)
75
+ reply(text, **opts)
76
+ end
77
+
78
+ def answer(text = nil, **opts)
79
+ reply(text, **opts)
80
+ end
81
+
82
+ def edit_text(text, **opts)
83
+ call_api("editMessageText", { chat_id: chat_id!, message_id: message_id, text: text.to_s }.merge(opts))
84
+ end
85
+
86
+ alias edit edit_text
87
+
88
+ def edit_caption(caption, **opts)
89
+ call_api("editMessageCaption", { chat_id: chat_id!, message_id: message_id, caption: caption.to_s }.merge(opts))
90
+ end
91
+
92
+ def edit_media(media, **opts)
93
+ call_api("editMessageMedia", { chat_id: chat_id!, message_id: message_id, media: media }.merge(opts))
94
+ end
95
+
96
+ def edit_checklist(checklist, **opts)
97
+ call_api("editMessageChecklist", { chat_id: chat_id!, message_id: message_id, checklist: checklist }.merge(opts))
98
+ end
99
+
100
+ def edit_reply_markup(reply_markup = nil, **opts)
101
+ call_api("editMessageReplyMarkup", { chat_id: chat_id!, message_id: message_id, reply_markup: reply_markup }.merge(opts))
102
+ end
103
+
104
+ def edit_live_location(latitude:, longitude:, **opts)
105
+ call_api("editMessageLiveLocation", { chat_id: chat_id!, message_id: message_id, latitude: latitude, longitude: longitude }.merge(opts))
106
+ end
107
+
108
+ def stop_live_location(**opts)
109
+ call_api("stopMessageLiveLocation", { chat_id: chat_id!, message_id: message_id }.merge(opts))
110
+ end
111
+
112
+ def forward(to_chat_id:, from_chat_id: chat_id!, **opts)
113
+ call_api("forwardMessage", { chat_id: to_chat_id, from_chat_id: from_chat_id, message_id: message_id }.merge(opts))
114
+ end
115
+
116
+ def copy(to_chat_id:, from_chat_id: chat_id!, **opts)
117
+ call_api("copyMessage", { chat_id: to_chat_id, from_chat_id: from_chat_id, message_id: message_id }.merge(opts))
118
+ end
119
+
120
+ def copy_media_group(to_chat_id:, from_chat_id: chat_id!, **opts)
121
+ call_api("copyMessages", { chat_id: to_chat_id, from_chat_id: from_chat_id, message_ids: [message_id] }.merge(opts))
122
+ end
123
+
124
+ def delete(**opts)
125
+ call_api("deleteMessage", { chat_id: chat_id!, message_id: message_id }.merge(opts))
126
+ end
127
+
128
+ def react(reaction:, is_big: false)
129
+ call_api("setMessageReaction", { chat_id: chat_id!, message_id: message_id, reaction: reaction, is_big: is_big })
130
+ end
131
+
132
+ def retract_vote(**opts)
133
+ call_api("stopPoll", { chat_id: chat_id!, message_id: message_id }.merge(opts))
134
+ end
135
+
136
+ def vote(option_ids, **opts)
137
+ call_api("sendPoll", { chat_id: chat_id!, options: option_ids }.merge(opts))
138
+ end
139
+
140
+ def pin(**opts)
141
+ call_api("pinChatMessage", { chat_id: chat_id!, message_id: message_id }.merge(opts))
142
+ end
143
+
144
+ def unpin(**opts)
145
+ call_api("unpinChatMessage", { chat_id: chat_id!, message_id: message_id }.merge(opts))
146
+ end
147
+
148
+ def read
149
+ call_raw_api("readChatHistory", { chat_id: chat_id! })
150
+ end
151
+
152
+ def view
153
+ call_raw_api("viewMessages", { chat_id: chat_id!, message_ids: [message_id] })
154
+ end
155
+
156
+ def pay(**opts)
157
+ call_raw_api("sendPaymentForm", { chat_id: chat_id!, message_id: message_id }.merge(opts))
158
+ end
159
+
160
+ def accept_gift_purchase_offer(**opts)
161
+ call_raw_api("processGiftPurchaseOffer", { message_id: message_id, accept: true }.merge(opts))
162
+ end
163
+
164
+ def reject_gift_purchase_offer(**opts)
165
+ call_raw_api("processGiftPurchaseOffer", { message_id: message_id, accept: false }.merge(opts))
166
+ end
167
+
168
+ def summarize(summary_language_code: "en")
169
+ call_raw_api("summarizeMessage", { chat_id: chat_id!, message_id: message_id, summary_language_code: summary_language_code })
170
+ end
171
+
172
+ def fix_text_with_ai(**opts)
173
+ call_raw_api("fixTextWithAi", { chat_id: chat_id!, message_id: message_id }.merge(opts))
174
+ end
175
+
176
+ def compose_text_with_ai(**opts)
177
+ call_raw_api("composeTextWithAi", { chat_id: chat_id!, message_id: message_id }.merge(opts))
178
+ end
179
+
180
+ def reply_inline_bot_result(result_id:, query_id:, **opts)
181
+ call_raw_api("sendInlineBotResult", { chat_id: chat_id!, query_id: query_id, result_id: result_id }.merge(opts))
182
+ end
183
+
184
+ def answer_inline_bot_result(result_id:, query_id:, **opts)
185
+ reply_inline_bot_result(result_id: result_id, query_id: query_id, **opts)
186
+ end
187
+
188
+ def get_media_group
189
+ return nil if media_group_id.to_s.empty?
190
+
191
+ call_raw_api("getMediaGroup", { chat_id: chat_id!, message_id: message_id })
192
+ end
193
+
194
+ def reply_chat_action(action)
195
+ call_api("sendChatAction", { chat_id: chat_id!, action: action })
196
+ end
197
+
198
+ def click
199
+ raise NotImplementedError, "click() requires callback query context"
200
+ end
201
+
202
+ def download(file_name = "file.dat")
203
+ file_id = resolve_file_id
204
+ raise ArgumentError, "message has no downloadable media" if file_id.nil?
205
+
206
+ f = call_api("getFile", { file_id: file_id })
207
+ call_raw_api("getFile", { file_id: file_id }) unless f
208
+ file_path = f && f["file_path"]
209
+ raise ArgumentError, "file_path not found for file_id=#{file_id}" if file_path.to_s.empty?
210
+
211
+ @api.download_file(file_path, file_name)
212
+ file_name
213
+ end
214
+
215
+ SENDERS = {
216
+ animation: "sendAnimation",
217
+ audio: "sendAudio",
218
+ contact: "sendContact",
219
+ document: "sendDocument",
220
+ game: "sendGame",
221
+ invoice: "sendInvoice",
222
+ location: "sendLocation",
223
+ media_group: "sendMediaGroup",
224
+ photo: "sendPhoto",
225
+ poll: "sendPoll",
226
+ dice: "sendDice",
227
+ sticker: "sendSticker",
228
+ venue: "sendVenue",
229
+ video: "sendVideo",
230
+ video_note: "sendVideoNote",
231
+ voice: "sendVoice",
232
+ paid_media: "sendPaidMedia",
233
+ cached_media: "sendDocument",
234
+ checklist: "sendChecklist"
235
+ }.freeze
236
+
237
+ SENDERS.each do |name, method_name|
238
+ define_method("reply_#{name}") do |payload = nil, **opts|
239
+ params = { chat_id: chat_id!, reply_to_message_id: message_id }.merge(opts)
240
+ params = attach_payload(name, params, payload)
241
+ call_api(method_name, params)
242
+ end
243
+
244
+ define_method("answer_#{name}") do |payload = nil, **opts|
245
+ public_send("reply_#{name}", payload, **opts)
246
+ end
247
+ end
248
+
249
+ private
250
+
251
+ def chat_id!
252
+ @chat&.id || self["chat"]&.dig("id") || raise(ArgumentError, "message has no chat id")
253
+ end
254
+
255
+ def attach_payload(kind, params, payload)
256
+ case kind
257
+ when :animation, :audio, :document, :photo, :sticker, :video, :video_note, :voice
258
+ params.merge(kind => payload)
259
+ when :contact
260
+ params.merge(payload.is_a?(Hash) ? payload : {})
261
+ when :game
262
+ params.merge(game_short_name: payload)
263
+ when :invoice
264
+ params.merge(payload.is_a?(Hash) ? payload : {})
265
+ when :location
266
+ params.merge(payload.is_a?(Hash) ? payload : {})
267
+ when :media_group
268
+ params.merge(media: payload)
269
+ when :poll
270
+ params.merge(payload.is_a?(Hash) ? payload : {})
271
+ when :venue
272
+ params.merge(payload.is_a?(Hash) ? payload : {})
273
+ when :paid_media
274
+ params.merge(payload.is_a?(Hash) ? payload : {})
275
+ when :cached_media
276
+ params.merge(document: payload)
277
+ when :checklist
278
+ params.merge(checklist: payload)
279
+ else
280
+ params
281
+ end
282
+ end
283
+
284
+ def resolve_file_id
285
+ return @document.file_id if @document&.respond_to?(:file_id)
286
+ return @audio.file_id if @audio&.respond_to?(:file_id)
287
+ return @video.file_id if @video&.respond_to?(:file_id)
288
+ return @voice.file_id if @voice&.respond_to?(:file_id)
289
+ return @animation.file_id if @animation&.respond_to?(:file_id)
290
+ return @photo.last.file_id if @photo.is_a?(Array) && @photo.last&.respond_to?(:file_id)
291
+
292
+ nil
293
+ end
294
+ end
295
+ end
@@ -0,0 +1,14 @@
1
+ require_relative "base_object"
2
+ require_relative "user"
3
+
4
+ module GrubY
5
+ class MessageEntity < BaseObject
6
+ fields :type, :offset, :length, :url, :user, :language, :custom_emoji_id,
7
+ :unix_time, :date_time_format
8
+
9
+ def initialize(data)
10
+ super(data)
11
+ @user = User.new(@user) if @user.is_a?(Hash)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,67 @@
1
+ require_relative "base_object"
2
+
3
+ module GrubY
4
+ module TypeRegistry
5
+ TYPE_NAMES = %w[
6
+ AcceptedGiftTypes Birthday BusinessConnection BusinessIntro BusinessRecipients BusinessWeeklyOpen BusinessWorkingHours
7
+ Username VerificationStatus ChatPhoto ChatMember ChatPermissions ChatAdministratorRights ChatInviteLink ChatAdminWithInviteLinks
8
+ ChatEvent ChatEventFilter ChatMemberUpdated ChatJoiner Dialog Restriction EmojiStatus FailedToAddMember Folder GroupCallMember
9
+ ChatColor FoundContacts PrivacyRule StoriesStealthMode UserRating BotVerification BusinessBotRights ChatSettings
10
+ GlobalPrivacySettings HistoryCleared BusinessMessage MessageOriginChannel MessageOriginChat MessageOriginHiddenUser
11
+ MessageOriginImport MessageOriginUser MessageOrigin Photo PollOptionAdded PollOptionDeleted Thumbnail StrippedThumbnail
12
+ AvailableEffect ExternalReplyInfo FactCheck FormattedText ForumTopic ForumTopicClosed ForumTopicCreated ForumTopicEdited
13
+ ForumTopicReopened GeneralForumTopicHidden GeneralForumTopicUnhidden Contact CraftGiftResult CraftGiftResultSuccess
14
+ CraftGiftResultFail Location ManagedBotCreated MaskPosition MediaArea Venue Sticker Game WebPage ProximityAlertTriggered
15
+ PollOption Dice Reaction RestrictionReason Gift VideoChatScheduled VideoChatStarted VideoChatEnded VideoChatMembersInvited
16
+ PhoneCallStarted PhoneCallEnded WebAppData MessageReactions ChatReactions MyBoost BoostsStatus Giveaway InputChecklistTask
17
+ GiveawayCreated GiveawayPrizeStars GiveawayCompleted GiveawayWinners Invoice LinkPreviewOptions GiftCollection PremiumGiftCode
18
+ GiftPurchaseLimit GiftResaleParameters GiftResalePrice GiftResalePriceStar GiftResalePriceTon GiftUpgradePreview
19
+ GiftUpgradePrice GiftUpgradeVariants CheckedGiftCode ChecklistTask ChecklistTasksAdded ChecklistTasksDone Checklist
20
+ RefundedPayment ReplyParameters SuccessfulPayment SuggestedPostParameters SuggestedPostInfo SuggestedPostPaid
21
+ SuggestedPostPrice SuggestedPostPriceStar SuggestedPostPriceTon SuggestedPostApprovalFailed SuggestedPostApproved
22
+ SuggestedPostDeclined SuggestedPostRefunded TextQuote PaidMediaInfo PaidMediaPreview PaidMessagesRefunded PaidReactor
23
+ PaidMessagesPriceChanged DirectMessagePriceChanged DirectMessagesTopic PaymentForm PaymentOption SavedCredentials PaymentResult
24
+ ChatBoost ChatOwnerChanged ChatOwnerLeft ChatHasProtectedContentToggled ChatHasProtectedContentDisableRequested
25
+ ContactRegistered ScreenshotTaken StarAmount WriteAccessAllowed GiftAttribute StoryView GiftedPremium ChatBackground ChatTheme
26
+ GiftedStars GiftedTon UpgradedGiftValueInfo UpgradedGiftAttributeId UpgradedGiftPurchaseOffer UpgradedGiftPurchaseOfferRejected
27
+ UpgradedGiftAttributeIdModel UpgradedGiftAttributeIdSymbol UpgradedGiftAttributeIdBackdrop UpgradedGiftAttributeRarity
28
+ UpgradedGiftAttributeRarityPerMille UpgradedGiftAttributeRarityUncommon UpgradedGiftAttributeRarityRare
29
+ UpgradedGiftAttributeRarityEpic UpgradedGiftAttributeRarityLegendary UpgradedGiftOriginalDetails InputChatPhoto
30
+ InputChatPhotoPrevious InputChatPhotoStatic InputChatPhotoAnimation AuctionBid AuctionRound AuctionState AuctionStateActive
31
+ AuctionStateFinished GiftAuctionState GiftAuction ReplyKeyboardMarkup KeyboardButton ReplyKeyboardRemove
32
+ InlineKeyboardMarkup InlineKeyboardButton LoginUrl ForceReply GameHighScore CallbackGame WebAppInfo MenuButton
33
+ MenuButtonCommands MenuButtonWebApp MenuButtonDefault SentWebAppMessage KeyboardButtonRequestChat
34
+ KeyboardButtonRequestManagedBot KeyboardButtonRequestUsers KeyboardButtonPollType ManagedBotUpdated OrderInfo
35
+ MessageReactionUpdated MessageReactionCountUpdated ChatBoostUpdated ShippingOption PurchasedPaidMedia ChatShared UsersShared
36
+ BotCommand BotCommandScope BotCommandScopeDefault BotCommandScopeAllPrivateChats BotCommandScopeAllGroupChats
37
+ BotCommandScopeAllChatAdministrators BotCommandScopeChat BotCommandScopeChatAdministrators BotCommandScopeChatMember
38
+ InlineQueryResult InlineQueryResultCachedAudio InlineQueryResultCachedDocument InlineQueryResultCachedAnimation
39
+ InlineQueryResultCachedPhoto InlineQueryResultCachedSticker InlineQueryResultCachedVideo InlineQueryResultCachedVoice
40
+ InlineQueryResultArticle InlineQueryResultAudio InlineQueryResultContact InlineQueryResultDocument InlineQueryResultAnimation
41
+ InlineQueryResultLocation InlineQueryResultPhoto InlineQueryResultVenue InlineQueryResultVideo InlineQueryResultVoice
42
+ ChosenInlineResult ActiveSessions FirebaseAuthenticationSettings FirebaseAuthenticationSettingsAndroid
43
+ FirebaseAuthenticationSettingsIos PhoneNumberAuthenticationSettings SentCode TermsOfService InputChecklist
44
+ InputContactMessageContent InputCredentials InputCredentialsApplePay InputCredentialsGooglePay InputCredentialsNew
45
+ InputCredentialsSaved InputInvoice InputInvoiceMessage InputInvoiceMessageContent InputInvoiceName
46
+ InputLocationMessageContent InputMedia InputMediaAnimation InputMediaAudio InputMediaDocument InputMediaPhoto
47
+ InputMediaVideo InputMessageContent InputPhoneContact InputPollOption InputPrivacyRule InputPrivacyRuleAllowAll
48
+ InputPrivacyRuleAllowBots InputPrivacyRuleAllowChats InputPrivacyRuleAllowCloseFriends InputPrivacyRuleAllowContacts
49
+ InputPrivacyRuleAllowPremium InputPrivacyRuleAllowUsers InputPrivacyRuleDisallowAll InputPrivacyRuleDisallowBots
50
+ InputPrivacyRuleDisallowChats InputPrivacyRuleDisallowContacts InputPrivacyRuleDisallowUsers InputTextMessageContent
51
+ InputVenueMessageContent
52
+ ].freeze
53
+
54
+ module_function
55
+
56
+ def install!
57
+ TYPE_NAMES.each do |type_name|
58
+ next if GrubY.const_defined?(type_name)
59
+
60
+ klass = Class.new(GrubY::BaseObject)
61
+ GrubY.const_set(type_name, klass)
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ GrubY::TypeRegistry.install!
@@ -0,0 +1,31 @@
1
+ require_relative "base_object"
2
+
3
+ module GrubY
4
+ class User < BaseObject
5
+ fields :id, :is_bot, :first_name, :last_name, :username, :language_code,
6
+ :is_premium, :added_to_attachment_menu, :can_join_groups,
7
+ :can_read_all_group_messages, :supports_inline_queries,
8
+ :can_connect_to_business, :has_main_web_app, :has_topics_enabled,
9
+ :allows_users_to_create_topics, :can_manage_bots
10
+
11
+ def archive
12
+ call_raw_api("archiveChats", { chat_ids: [id] })
13
+ end
14
+
15
+ def unarchive
16
+ call_raw_api("unarchiveChats", { chat_ids: [id] })
17
+ end
18
+
19
+ def block
20
+ call_raw_api("blockUser", { user_id: id })
21
+ end
22
+
23
+ def unblock
24
+ call_raw_api("unblockUser", { user_id: id })
25
+ end
26
+
27
+ def get_common_chats(offset_chat_id: 0, limit: 100)
28
+ call_raw_api("getCommonChats", { user_id: id, offset_chat_id: offset_chat_id, limit: limit })
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ module GrubY
2
+ module WebApp
3
+ module_function
4
+
5
+ def info(url:)
6
+ {
7
+ web_app: {
8
+ url: url.to_s
9
+ }
10
+ }
11
+ end
12
+
13
+ def inline_button(text:, url:)
14
+ {
15
+ text: text.to_s,
16
+ web_app: {
17
+ url: url.to_s
18
+ }
19
+ }
20
+ end
21
+ end
22
+ end
data/lib/grubY.rb ADDED
@@ -0,0 +1,41 @@
1
+ require_relative "grubY/async"
2
+ require_relative "grubY/api"
3
+ require_relative "grubY/bot"
4
+ require_relative "grubY/bound"
5
+ require_relative "grubY/context"
6
+ require_relative "grubY/client"
7
+ require_relative "grubY/dispatcher"
8
+ require_relative "grubY/enums"
9
+ require_relative "grubY/file_stream"
10
+ require_relative "grubY/filters"
11
+ require_relative "grubY/handlers"
12
+ require_relative "grubY/group_manager"
13
+ require_relative "grubY/keyboard"
14
+ require_relative "grubY/media"
15
+ require_relative "grubY/middleware"
16
+ require_relative "grubY/ntgcalls"
17
+ require_relative "grubY/plugin"
18
+ require_relative "grubY/raw"
19
+ require_relative "grubY/raw_types"
20
+ require_relative "grubY/retry"
21
+ require_relative "grubY/server"
22
+ require_relative "grubY/session"
23
+ require_relative "grubY/webapp"
24
+ require_relative "grubY/types/base_object"
25
+ require_relative "grubY/types/user"
26
+ require_relative "grubY/types/chat"
27
+ require_relative "grubY/types/bound_entities"
28
+ require_relative "grubY/types/chat_info"
29
+ require_relative "grubY/types/message_entity"
30
+ require_relative "grubY/types/extra"
31
+ require_relative "grubY/types/message"
32
+ require_relative "grubY/types/registry"
33
+ require_relative "grubY/tdlib/native"
34
+ require_relative "grubY/tdlib/errors"
35
+ require_relative "grubY/tdlib/decorators"
36
+ require_relative "grubY/tdlib/tdjson"
37
+ require_relative "grubY/tdlib/schema_builder"
38
+ require_relative "grubY/tdlib/client_manager"
39
+ require_relative "grubY/tdlib/client"
40
+ require_relative "grubY/tdlib/group_manager"
41
+ require_relative "grubY/tdlib/user_session"
data/plugins/logger.rb ADDED
@@ -0,0 +1,7 @@
1
+ def self.register(bot)
2
+ bot.use do |ctx, nxt|
3
+ username = ctx.user&.username || ctx.user&.first_name || "unknown"
4
+ puts "[LOG] #{username}: #{ctx.update}"
5
+ nxt.call
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ require "shellwords"
2
+
3
+ def self.register(bot)
4
+ bot.on(:message) do |ctx|
5
+ next unless ctx.file_id
6
+
7
+ file = ctx.download("input.dat")
8
+ safe_file = Shellwords.escape(file)
9
+ system("ffmpeg -i #{safe_file} output.mp3")
10
+
11
+ ctx.reply("Processed file..")
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gruubY
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Sreyanshu
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ffi
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: Telegram BotAPI and TDLib toolkit for Ruby, with direct NTgCalls native
27
+ bindings.
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - LICENSE
33
+ - README.md
34
+ - Rakefile
35
+ - config/config.rb
36
+ - example/bot.rb
37
+ - example/generate_user_session.rb
38
+ - example/ntgcalls.rb
39
+ - example/tdlib.rb
40
+ - example/userbot.rb
41
+ - lib/grubY.rb
42
+ - lib/grubY/api.rb
43
+ - lib/grubY/async.rb
44
+ - lib/grubY/bot.rb
45
+ - lib/grubY/bound.rb
46
+ - lib/grubY/client.rb
47
+ - lib/grubY/context.rb
48
+ - lib/grubY/dispatcher.rb
49
+ - lib/grubY/enums.rb
50
+ - lib/grubY/exception.rb
51
+ - lib/grubY/file_stream.rb
52
+ - lib/grubY/filters.rb
53
+ - lib/grubY/group_manager.rb
54
+ - lib/grubY/handlers.rb
55
+ - lib/grubY/keyboard.rb
56
+ - lib/grubY/media.rb
57
+ - lib/grubY/middleware.rb
58
+ - lib/grubY/ntgcalls.rb
59
+ - lib/grubY/ntgcalls/native.rb
60
+ - lib/grubY/plugin.rb
61
+ - lib/grubY/raw.rb
62
+ - lib/grubY/raw_types.rb
63
+ - lib/grubY/retry.rb
64
+ - lib/grubY/server.rb
65
+ - lib/grubY/session.rb
66
+ - lib/grubY/tdlib/client.rb
67
+ - lib/grubY/tdlib/client_manager.rb
68
+ - lib/grubY/tdlib/decorators.rb
69
+ - lib/grubY/tdlib/errors.rb
70
+ - lib/grubY/tdlib/group_manager.rb
71
+ - lib/grubY/tdlib/native.rb
72
+ - lib/grubY/tdlib/schema_builder.rb
73
+ - lib/grubY/tdlib/tdjson.rb
74
+ - lib/grubY/tdlib/user_session.rb
75
+ - lib/grubY/types/base_object.rb
76
+ - lib/grubY/types/bound_entities.rb
77
+ - lib/grubY/types/chat.rb
78
+ - lib/grubY/types/chat_info.rb
79
+ - lib/grubY/types/extra.rb
80
+ - lib/grubY/types/message.rb
81
+ - lib/grubY/types/message_entity.rb
82
+ - lib/grubY/types/registry.rb
83
+ - lib/grubY/types/user.rb
84
+ - lib/grubY/webapp.rb
85
+ - plugins/logger.rb
86
+ - plugins/media_tools.rb
87
+ homepage: https://github.com/iSreyanshu/grubY
88
+ licenses:
89
+ - MIT
90
+ metadata:
91
+ homepage_uri: https://github.com/iSreyanshu/grubY
92
+ source_code_uri: https://github.com/iSreyanshu/grubY
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '3.1'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubygems_version: 4.0.11
108
+ specification_version: 4
109
+ summary: A Ruby wrapper for Telegram BotAPI and TDLib
110
+ test_files: []