telegem 3.2.1 → 3.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Readme.md +1 -1
- data/bin/telegem-ssl +0 -0
- data/docs/.gitkeep +0 -0
- data/docs/ctx.md +437 -0
- data/docs/file_extract.md +378 -0
- data/lib/core/bot.rb +17 -1
- data/lib/markup/keyboard.rb +26 -16
- data/lib/plugins/file_extract.rb +172 -66
- data/lib/telegem.rb +8 -13
- metadata +42 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 64cc027dc87d2e24f181a24705a85243f95c7f498a44f70fcb175d8a9b2dd597
|
|
4
|
+
data.tar.gz: 37310a9a9c973f31f3dfd5b93e8347843a50c8218475b90a7f055df116c8353e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9cd4708d09629445cf1398677521270c22991eee81b45204d2384570ba14876c937888cf86fc9ba8bfdad78138a48ea9bee6fed6e019a12ae89b29433f91e881
|
|
7
|
+
data.tar.gz: ee85cb0026f096291a1700d825e68cf21f08385e1c7eaf5396763e00fbe4edecfb574b4ed1017293e4e41a06d60b98be5963893b6b0ba2e53f8816396ae33dfc
|
data/Readme.md
CHANGED
data/bin/telegem-ssl
CHANGED
|
File without changes
|
data/docs/.gitkeep
ADDED
|
File without changes
|
data/docs/ctx.md
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
The Context object (ctx) is the heart of every Telegem bot handler. It provides access to everything about the current update and methods to interact with Telegram.
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
📦 Basic Properties
|
|
6
|
+
|
|
7
|
+
Property Type Description
|
|
8
|
+
ctx.update Update Raw Telegram update object
|
|
9
|
+
ctx.bot Bot The bot instance
|
|
10
|
+
ctx.state Hash Temporary state for current request (cleared after)
|
|
11
|
+
ctx.session Hash Persistent user session (stored between requests)
|
|
12
|
+
ctx.match MatchData Regex match data from hears or pattern matching
|
|
13
|
+
ctx.scene String Current scene name (if in a scene)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
👤 User & Chat Information
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
ctx.from # User who sent the message
|
|
21
|
+
ctx.from.id # User ID
|
|
22
|
+
ctx.from.username # Username (may be nil)
|
|
23
|
+
ctx.from.first_name
|
|
24
|
+
ctx.from.last_name
|
|
25
|
+
|
|
26
|
+
ctx.chat # Current chat
|
|
27
|
+
ctx.chat.id # Chat ID
|
|
28
|
+
ctx.chat.type # "private", "group", "supergroup", "channel"
|
|
29
|
+
|
|
30
|
+
ctx.user_id # Shortcut for ctx.from&.id
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
📨 Message Access
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
ctx.message # Current message
|
|
39
|
+
ctx.message.text # Message text
|
|
40
|
+
ctx.message.caption # Caption for media
|
|
41
|
+
ctx.message.message_id
|
|
42
|
+
ctx.message.date
|
|
43
|
+
|
|
44
|
+
ctx.message.reply_to_message # Message being replied to
|
|
45
|
+
ctx.reply_to_message # Same as above
|
|
46
|
+
|
|
47
|
+
ctx.message.photo # Array of photo sizes
|
|
48
|
+
ctx.message.document # Document object
|
|
49
|
+
ctx.message.audio
|
|
50
|
+
ctx.message.video
|
|
51
|
+
ctx.message.voice
|
|
52
|
+
ctx.message.sticker
|
|
53
|
+
ctx.message.location
|
|
54
|
+
|
|
55
|
+
ctx.message.entities # Formatting entities
|
|
56
|
+
ctx.message.caption_entities # Caption entities
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
🔍 Update Type Detection
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
ctx.callback_query # Callback query object (if present)
|
|
65
|
+
ctx.inline_query # Inline query object
|
|
66
|
+
ctx.chosen_inline_result
|
|
67
|
+
ctx.poll # Poll object
|
|
68
|
+
ctx.poll_answer
|
|
69
|
+
ctx.chat_member
|
|
70
|
+
ctx.my_chat_member
|
|
71
|
+
ctx.chat_join_request
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
📝 Message Content Shortcuts
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
ctx.text # ctx.message&.text
|
|
80
|
+
ctx.data # ctx.callback_query&.data
|
|
81
|
+
ctx.query # ctx.inline_query&.query
|
|
82
|
+
ctx.command? # True if message is a command
|
|
83
|
+
ctx.command # Command name (e.g., "start")
|
|
84
|
+
ctx.command_args # Arguments after command
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
💬 Sending Messages
|
|
90
|
+
|
|
91
|
+
Basic Text
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
ctx.reply("Hello world") # Simple reply
|
|
95
|
+
ctx.reply("Hello", parse_mode: "Markdown") # With formatting
|
|
96
|
+
ctx.reply("Hello", disable_web_page_preview: true)
|
|
97
|
+
ctx.reply("Hello", reply_to_message_id: 123)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
With Keyboard
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
# Reply keyboard
|
|
104
|
+
keyboard = Telegem::Markup.keyboard do
|
|
105
|
+
button "Option 1"
|
|
106
|
+
button "Option 2"
|
|
107
|
+
request_location "Share Location"
|
|
108
|
+
end
|
|
109
|
+
ctx.reply("Choose:", reply_markup: keyboard)
|
|
110
|
+
|
|
111
|
+
# Inline keyboard
|
|
112
|
+
inline = Telegem::Markup.inline do
|
|
113
|
+
callback "Yes", "confirm"
|
|
114
|
+
callback "No", "cancel"
|
|
115
|
+
url "Visit", "https://example.com"
|
|
116
|
+
end
|
|
117
|
+
ctx.reply("Confirm?", reply_markup: inline)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Remove Keyboard
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
ctx.remove_keyboard # Just removes keyboard
|
|
124
|
+
ctx.remove_keyboard("Done!") # Sends message + removes keyboard
|
|
125
|
+
ctx.remove_keyboard(selective: true) # Only for specific users
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Force Reply
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
ctx.reply("What's your name?", reply_markup: Telegem::Markup.force_reply)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
🖼️ Sending Media
|
|
137
|
+
|
|
138
|
+
Photos
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
ctx.photo("https://example.com/image.jpg")
|
|
142
|
+
ctx.photo("https://example.com/image.jpg", caption: "Beautiful gem")
|
|
143
|
+
ctx.photo(File.open("local.jpg"))
|
|
144
|
+
ctx.photo(File.open("local.jpg"), caption: "Local file")
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Documents
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
ctx.document("https://example.com/file.pdf")
|
|
151
|
+
ctx.document(File.open("report.pdf"), caption: "Monthly report")
|
|
152
|
+
ctx.document(file_id) # Using Telegram file_id
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Audio
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
ctx.audio("song.mp3", title: "My Song", performer: "Artist", duration: 180)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Video
|
|
162
|
+
|
|
163
|
+
```ruby
|
|
164
|
+
ctx.video("video.mp4", caption: "Check this out", width: 1920, height: 1080)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Voice
|
|
168
|
+
|
|
169
|
+
```ruby
|
|
170
|
+
ctx.voice("voice.ogg") # Must be OGG format
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Sticker
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
ctx.sticker("CAACAgIAAxkBAAIBZmd...") # Sticker file_id
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Location
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
ctx.location(6.454, 3.394) # Latitude, Longitude
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Contact
|
|
186
|
+
|
|
187
|
+
```ruby
|
|
188
|
+
ctx.contact("+1234567890", "John", last_name: "Doe")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
✏️ Editing Messages
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
ctx.edit_message_text("Updated text")
|
|
197
|
+
ctx.edit_message_text("New text", message_id: 123) # Specific message
|
|
198
|
+
|
|
199
|
+
ctx.edit_message_caption("New caption")
|
|
200
|
+
ctx.edit_message_media(new_photo)
|
|
201
|
+
ctx.edit_message_reply_markup(new_keyboard)
|
|
202
|
+
|
|
203
|
+
ctx.edit_message_live_location(6.455, 3.395) # For live locations
|
|
204
|
+
ctx.stop_message_live_location
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
❌ Deleting Messages
|
|
210
|
+
|
|
211
|
+
```ruby
|
|
212
|
+
ctx.delete_message # Deletes current message
|
|
213
|
+
ctx.delete_message(123) # Deletes specific message ID
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
🔄 Replying to Callbacks
|
|
219
|
+
|
|
220
|
+
```ruby
|
|
221
|
+
ctx.answer_callback_query("Done!") # Simple toast
|
|
222
|
+
ctx.answer_callback_query("Error!", show_alert: true) # Alert popup
|
|
223
|
+
ctx.answer_callback_query(url: "https://example.com") # Open URL
|
|
224
|
+
ctx.answer_callback_query(text: "Loading...", cache_time: 5)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
🔎 Inline Queries
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
ctx.answer_inline_query(results, cache_time: 300)
|
|
233
|
+
ctx.answer_inline_query(results, next_offset: "20") # Pagination
|
|
234
|
+
|
|
235
|
+
# Results array of InlineQueryResult objects
|
|
236
|
+
results = [
|
|
237
|
+
Telegem::Types::InlineQueryResultArticle.new(
|
|
238
|
+
id: "1",
|
|
239
|
+
title: "Result",
|
|
240
|
+
input_message_content: { message_text: "Text" }
|
|
241
|
+
)
|
|
242
|
+
]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
📥 File Operations
|
|
248
|
+
|
|
249
|
+
```ruby
|
|
250
|
+
ctx.download_file(file_id, "local/path") # Download file
|
|
251
|
+
ctx.file(file_id) # Get file info
|
|
252
|
+
ctx.file_path(file_id) # Get path on Telegram servers
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
🎬 Chat Actions (Typing Indicators)
|
|
258
|
+
|
|
259
|
+
```ruby
|
|
260
|
+
ctx.typing # "typing..."
|
|
261
|
+
ctx.uploading_photo # "sending photo..."
|
|
262
|
+
ctx.uploading_video # "sending video..."
|
|
263
|
+
ctx.uploading_audio # "sending audio..."
|
|
264
|
+
ctx.uploading_document # "sending document..."
|
|
265
|
+
ctx.find_location # "finding location..."
|
|
266
|
+
ctx.record_video # "recording video..."
|
|
267
|
+
ctx.record_audio # "recording audio..."
|
|
268
|
+
ctx.choose_sticker # "choosing sticker..."
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
All accept optional **options:
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
ctx.typing(business_connection_id: "123") # For business connections
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
👥 Chat Management
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
ctx.kick_chat_member(user_id) # Kick user
|
|
283
|
+
ctx.ban_chat_member(user_id, until_date: future_time)
|
|
284
|
+
ctx.unban_chat_member(user_id, only_if_banned: true)
|
|
285
|
+
|
|
286
|
+
ctx.restrict_chat_member(user_id, permissions: { can_send_messages: false })
|
|
287
|
+
ctx.promote_chat_member(user_id, can_invite_users: true)
|
|
288
|
+
|
|
289
|
+
ctx.get_chat_administrators
|
|
290
|
+
ctx.get_chat_member(user_id)
|
|
291
|
+
ctx.get_chat_members_count
|
|
292
|
+
|
|
293
|
+
ctx.leave_chat
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
📌 Pinning Messages
|
|
299
|
+
|
|
300
|
+
```ruby
|
|
301
|
+
ctx.pin_message(123) # Pin message
|
|
302
|
+
ctx.pin_message(123, disable_notification: true)
|
|
303
|
+
ctx.unpin_message # Unpin current
|
|
304
|
+
ctx.unpin_message(123) # Unpin specific
|
|
305
|
+
ctx.unpin_all_messages
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
🔁 Forwarding & Copying
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
ctx.forward_message(from_chat_id, message_id)
|
|
314
|
+
ctx.copy_message(from_chat_id, message_id, caption: "New caption")
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
🌐 Web App & Polls
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
ctx.web_app_data # Data from Web App
|
|
323
|
+
|
|
324
|
+
ctx.send_poll("Question?", ["Option1", "Option2"], is_anonymous: true)
|
|
325
|
+
ctx.stop_poll(message_id)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
🎭 Scenes (Multi-step Conversations)
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
ctx.enter_scene(:survey) # Enter scene
|
|
334
|
+
ctx.leave_scene # Leave current scene
|
|
335
|
+
ctx.leave_scene(reason: :cancel) # Leave with reason
|
|
336
|
+
ctx.in_scene? # Check if in a scene
|
|
337
|
+
ctx.current_scene # Get current scene name
|
|
338
|
+
|
|
339
|
+
ctx.ask("What's your name?") # Prompt for response (scene helper)
|
|
340
|
+
ctx.next_step # Move to next scene step
|
|
341
|
+
ctx.next_step(:payment) # Move to specific step
|
|
342
|
+
ctx.scene_data # Get scene data hash
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
🎨 Keyboard Building Helpers
|
|
348
|
+
|
|
349
|
+
```ruby
|
|
350
|
+
# Create and use in one line
|
|
351
|
+
ctx.reply_with_keyboard("Choose:", Telegem::Markup.keyboard { button "Yes" })
|
|
352
|
+
|
|
353
|
+
ctx.reply_with_inline_keyboard("Options:", Telegem::Markup.inline { callback "Yes", "data" })
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
📊 Poll Helpers
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
ctx.poll? # True if update is a poll
|
|
362
|
+
ctx.poll_answer? # True if poll answer
|
|
363
|
+
ctx.poll_answer # Get poll answer object
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
⏱️ Timing & Metadata
|
|
369
|
+
|
|
370
|
+
```ruby
|
|
371
|
+
ctx.logger # Bot's logger
|
|
372
|
+
ctx.api # Direct API client
|
|
373
|
+
ctx.raw_update # Original update hash
|
|
374
|
+
ctx.update_id # Update ID
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
🔄 Session Management
|
|
380
|
+
|
|
381
|
+
```ruby
|
|
382
|
+
ctx.session[:user_preference] = "dark" # Store in session
|
|
383
|
+
pref = ctx.session[:user_preference] # Retrieve
|
|
384
|
+
ctx.session.delete(:temp_data) # Delete
|
|
385
|
+
ctx.session.clear # Clear all
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
🎯 Complete Usage Example
|
|
391
|
+
|
|
392
|
+
```ruby
|
|
393
|
+
bot.command('start') do |ctx|
|
|
394
|
+
ctx.session[:visits] ||= 0
|
|
395
|
+
ctx.session[:visits] += 1
|
|
396
|
+
|
|
397
|
+
keyboard = Telegem::Markup.keyboard do
|
|
398
|
+
button "💎 Random Gem"
|
|
399
|
+
request_location "📍 Share Location"
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
ctx.reply(
|
|
403
|
+
"Welcome! You've visited #{ctx.session[:visits]} times",
|
|
404
|
+
reply_markup: keyboard
|
|
405
|
+
)
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
bot.hears(/^gem$/i) do |ctx|
|
|
409
|
+
ctx.typing
|
|
410
|
+
sleep 1 # Simulate processing
|
|
411
|
+
|
|
412
|
+
gem = GemDatabase.random
|
|
413
|
+
ctx.photo(gem.image_url, caption: "#{gem.name}\n#{gem.fact}")
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
bot.callback_query('favorite') do |ctx|
|
|
417
|
+
gem_id = ctx.data.split('_').last
|
|
418
|
+
ctx.session[:favorites] ||= []
|
|
419
|
+
ctx.session[:favorites] << gem_id
|
|
420
|
+
|
|
421
|
+
ctx.answer_callback_query("Added to favorites! ❤️")
|
|
422
|
+
ctx.edit_message_text("⭐ Favorited!")
|
|
423
|
+
end
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
⚠️ Error Handling
|
|
429
|
+
|
|
430
|
+
```ruby
|
|
431
|
+
bot.error do |error, ctx|
|
|
432
|
+
ctx.logger.error("Error for user #{ctx.user_id}: #{error.message}")
|
|
433
|
+
ctx.reply("Something went wrong. Please try again.") if ctx.chat
|
|
434
|
+
end
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|