telegem 2.0.7 → 2.0.9
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/Test-Projects/Movie-tracker-bot/Gemfile +2 -0
- data/Test-Projects/Movie-tracker-bot/bot.rb +62 -0
- data/Test-Projects/Movie-tracker-bot/handlers/.gitkeep +0 -0
- data/Test-Projects/Movie-tracker-bot/handlers/add_1_.rb +160 -0
- data/Test-Projects/Movie-tracker-bot/handlers/add_2_.rb +139 -0
- data/Test-Projects/Movie-tracker-bot/handlers/premium.rb +13 -0
- data/Test-Projects/Movie-tracker-bot/handlers/report.rb +31 -0
- data/Test-Projects/Movie-tracker-bot/handlers/search.rb +150 -0
- data/Test-Projects/Movie-tracker-bot/handlers/sponsor.rb +14 -0
- data/Test-Projects/Movie-tracker-bot/handlers/start.rb +48 -0
- data/Test-Projects/Movie-tracker-bot/handlers/watch.rb +210 -0
- data/Test-Projects/Test-submitted-by-marvel/.gitkeep +0 -0
- data/Test-Projects/Test-submitted-by-marvel/Marvel-bot.md +3 -0
- data/docs-src/.gitkeep +0 -0
- data/docs-src/Bot-registration_.PNG +0 -0
- data/docs-src/bot.md +295 -0
- data/docs-src/context|ctx|.md +531 -0
- data/docs-src/getting-started.md +328 -0
- data/docs-src/keyboard_inline.md +413 -0
- data/docs-src/scene.md +509 -0
- data/docs-src/understanding-ctx.md +581 -0
- data/lib/api/client.rb +17 -16
- data/lib/core/bot.rb +19 -25
- data/lib/telegem.rb +1 -1
- data/lib/webhook/server.rb +1 -1
- metadata +26 -15
- data/docs/Api.md +0 -211
- data/docs/Cookbook(copy_paste).md +0 -644
- data/docs/Getting_started.md +0 -348
- data/docs/How_to_use.md +0 -571
- data/docs/QuickStart.md +0 -258
- data/docs/Understanding_Scene.md +0 -434
- data/docs/Usage.md +0 -717
- data/docs/webhook_setup.md +0 -199
- /data/{docs → Test-Projects/Movie-tracker-bot}/.gitkeep +0 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
|
|
2
|
+
# Context API Reference
|
|
3
|
+
|
|
4
|
+
The `Telegem::Core::Context` object provides access to the current update and helper methods for responding.
|
|
5
|
+
|
|
6
|
+
## Accessing Update Data
|
|
7
|
+
|
|
8
|
+
### Basic Accessors
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
ctx.update # Raw Telegem::Types::Update object
|
|
12
|
+
ctx.message # Current message (Telegem::Types::Message)
|
|
13
|
+
ctx.callback_query # Callback query object
|
|
14
|
+
ctx.inline_query # Inline query object
|
|
15
|
+
ctx.from # User who sent the update (Telegem::Types::User)
|
|
16
|
+
ctx.chat # Chat where update originated (Telegem::Types::Chat)
|
|
17
|
+
ctx.data # Callback query data (String)
|
|
18
|
+
ctx.query # Inline query text (String)
|
|
19
|
+
ctx.state # Hash for temporary state storage
|
|
20
|
+
ctx.session # Persistent session storage (Hash)
|
|
21
|
+
ctx.match # Regex match data from `hears` or `command`
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Common Patterns
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
# Check message type
|
|
28
|
+
if ctx.message.text
|
|
29
|
+
puts "Text message: #{ctx.message.text}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Get user info
|
|
33
|
+
user_id = ctx.from.id
|
|
34
|
+
username = ctx.from.username
|
|
35
|
+
full_name = ctx.from.full_name # "John Doe"
|
|
36
|
+
|
|
37
|
+
# Get chat info
|
|
38
|
+
chat_id = ctx.chat.id
|
|
39
|
+
chat_type = ctx.chat.type # "private", "group", "supergroup", "channel"
|
|
40
|
+
|
|
41
|
+
# Check if callback query
|
|
42
|
+
if ctx.callback_query
|
|
43
|
+
puts "Button clicked: #{ctx.data}"
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Message Sending Methods
|
|
48
|
+
|
|
49
|
+
reply(text, **options)
|
|
50
|
+
|
|
51
|
+
Sends a text message to the current chat.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
ctx.reply("Hello World!")
|
|
55
|
+
ctx.reply("Formatted text", parse_mode: "HTML")
|
|
56
|
+
ctx.reply("With reply", reply_to_message_id: ctx.message.message_id)
|
|
57
|
+
|
|
58
|
+
# With keyboard
|
|
59
|
+
keyboard = Telegem.keyboard { row "Yes", "No" }
|
|
60
|
+
ctx.reply("Choose one:", reply_markup: keyboard)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Options:
|
|
64
|
+
|
|
65
|
+
· parse_mode: "Markdown", "HTML", or "MarkdownV2"
|
|
66
|
+
· reply_to_message_id: Reply to specific message
|
|
67
|
+
· reply_markup: Keyboard or inline markup
|
|
68
|
+
· disable_web_page_preview: Boolean
|
|
69
|
+
· disable_notification: Boolean
|
|
70
|
+
|
|
71
|
+
Media Methods
|
|
72
|
+
|
|
73
|
+
photo(photo, caption: nil, **options)
|
|
74
|
+
|
|
75
|
+
Sends a photo.
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
# From URL
|
|
79
|
+
ctx.photo("https://example.com/image.jpg")
|
|
80
|
+
|
|
81
|
+
# From local file
|
|
82
|
+
ctx.photo(File.open("image.jpg"))
|
|
83
|
+
|
|
84
|
+
# With caption
|
|
85
|
+
ctx.photo("image.jpg", caption: "Nice photo!")
|
|
86
|
+
|
|
87
|
+
# With custom options
|
|
88
|
+
ctx.photo("image.jpg",
|
|
89
|
+
caption: "Sunset",
|
|
90
|
+
parse_mode: "HTML",
|
|
91
|
+
disable_notification: true
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
document(document, caption: nil, **options)
|
|
96
|
+
|
|
97
|
+
Sends a document.
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
ctx.document(File.open("report.pdf"), caption: "Monthly report")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
audio(audio, caption: nil, **options)
|
|
104
|
+
|
|
105
|
+
Sends an audio file.
|
|
106
|
+
|
|
107
|
+
```ruby
|
|
108
|
+
ctx.audio(File.open("song.mp3"), caption: "My song")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
video(video, caption: nil, **options)
|
|
112
|
+
|
|
113
|
+
Sends a video.
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
ctx.video(File.open("video.mp4"), caption: "Funny cat")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
voice(voice, caption: nil, **options)
|
|
120
|
+
|
|
121
|
+
Sends a voice message.
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
ctx.voice(File.open("voice.ogg"), caption: "My voice")
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
sticker(sticker, **options)
|
|
128
|
+
|
|
129
|
+
Sends a sticker.
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
ctx.sticker("CAACAgIAAxkBAAIB")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
location(latitude, longitude, **options)
|
|
136
|
+
|
|
137
|
+
Sends a location.
|
|
138
|
+
|
|
139
|
+
```ruby
|
|
140
|
+
ctx.location(40.7128, -74.0060) # New York
|
|
141
|
+
ctx.location(51.5074, -0.1278, live_period: 3600) # Live location for 1 hour
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Message Editing Methods
|
|
145
|
+
|
|
146
|
+
edit_message_text(text, **options)
|
|
147
|
+
|
|
148
|
+
Edits text of a message.
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
ctx.edit_message_text("Updated text")
|
|
152
|
+
ctx.edit_message_text("New text <b>bold</b>", parse_mode: "HTML")
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
edit_message_reply_markup(reply_markup, **options)
|
|
156
|
+
|
|
157
|
+
Edits only the reply markup of a message.
|
|
158
|
+
|
|
159
|
+
```ruby
|
|
160
|
+
new_keyboard = Telegem.inline do
|
|
161
|
+
row button "New Button", callback_data: "new"
|
|
162
|
+
end
|
|
163
|
+
ctx.edit_message_reply_markup(new_keyboard)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Message Management
|
|
167
|
+
|
|
168
|
+
delete_message(message_id = nil)
|
|
169
|
+
|
|
170
|
+
Deletes a message.
|
|
171
|
+
|
|
172
|
+
```ruby
|
|
173
|
+
ctx.delete_message # Delete current message
|
|
174
|
+
ctx.delete_message(123) # Delete specific message
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
forward_message(from_chat_id, message_id, **options)
|
|
178
|
+
|
|
179
|
+
Forwards a message.
|
|
180
|
+
|
|
181
|
+
```ruby
|
|
182
|
+
ctx.forward_message(-100123456789, 42) # From channel to current chat
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
copy_message(from_chat_id, message_id, **options)
|
|
186
|
+
|
|
187
|
+
Copies a message.
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
ctx.copy_message(-100123456789, 42, caption: "Copied!")
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
pin_message(message_id, **options)
|
|
194
|
+
|
|
195
|
+
Pins a message.
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
ctx.pin_message(ctx.message.message_id)
|
|
199
|
+
ctx.pin_message(123, disable_notification: true)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
unpin_message(**options)
|
|
203
|
+
|
|
204
|
+
Unpins a message.
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
207
|
+
ctx.unpin_message
|
|
208
|
+
ctx.unpin_message(message_id: 123) # Unpin specific message
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Chat Actions
|
|
212
|
+
|
|
213
|
+
send_chat_action(action, **options)
|
|
214
|
+
|
|
215
|
+
Shows a chat action (typing, uploading, etc.).
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
ctx.send_chat_action('typing')
|
|
219
|
+
ctx.send_chat_action('upload_photo')
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Available actions:
|
|
223
|
+
|
|
224
|
+
· typing
|
|
225
|
+
· upload_photo
|
|
226
|
+
· record_video
|
|
227
|
+
· upload_video
|
|
228
|
+
· record_audio
|
|
229
|
+
· upload_audio
|
|
230
|
+
· upload_document
|
|
231
|
+
· find_location
|
|
232
|
+
· record_video_note
|
|
233
|
+
· upload_video_note
|
|
234
|
+
|
|
235
|
+
Convenience Methods
|
|
236
|
+
|
|
237
|
+
```ruby
|
|
238
|
+
ctx.typing # Same as send_chat_action('typing')
|
|
239
|
+
ctx.uploading_photo # Same as send_chat_action('upload_photo')
|
|
240
|
+
ctx.uploading_video # Same as send_chat_action('upload_video')
|
|
241
|
+
ctx.uploading_audio # Same as send_chat_action('upload_audio')
|
|
242
|
+
ctx.uploading_document # Same as send_chat_action('upload_document')
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
with_typing(&block)
|
|
246
|
+
|
|
247
|
+
Wraps code block with typing indicator.
|
|
248
|
+
|
|
249
|
+
```ruby
|
|
250
|
+
ctx.with_typing do
|
|
251
|
+
# Long operation
|
|
252
|
+
sleep 2
|
|
253
|
+
ctx.reply("Done!")
|
|
254
|
+
end
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Inline Query Responses
|
|
258
|
+
|
|
259
|
+
answer_callback_query(text: nil, show_alert: false, **options)
|
|
260
|
+
|
|
261
|
+
Answers a callback query (inline button click).
|
|
262
|
+
|
|
263
|
+
```ruby
|
|
264
|
+
ctx.answer_callback_query(text: "Button clicked!")
|
|
265
|
+
ctx.answer_callback_query(text: "Error!", show_alert: true)
|
|
266
|
+
ctx.answer_callback_query(url: "https://example.com") # Open URL
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
answer_inline_query(results, **options)
|
|
270
|
+
|
|
271
|
+
Answers an inline query.
|
|
272
|
+
|
|
273
|
+
```ruby
|
|
274
|
+
results = [
|
|
275
|
+
{
|
|
276
|
+
type: "article",
|
|
277
|
+
id: "1",
|
|
278
|
+
title: "Result 1",
|
|
279
|
+
input_message_content: { message_text: "You selected 1" }
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
|
|
283
|
+
ctx.answer_inline_query(results, cache_time: 300)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Chat Management
|
|
287
|
+
|
|
288
|
+
kick_chat_member(user_id, **options)
|
|
289
|
+
|
|
290
|
+
Kicks a user from the chat.
|
|
291
|
+
|
|
292
|
+
```ruby
|
|
293
|
+
ctx.kick_chat_member(123456789)
|
|
294
|
+
ctx.kick_chat_member(123456789, until_date: Time.now + 86400) # 24 hour ban
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
ban_chat_member(user_id, **options)
|
|
298
|
+
|
|
299
|
+
Bans a user from the chat.
|
|
300
|
+
|
|
301
|
+
```ruby
|
|
302
|
+
ctx.ban_chat_member(123456789)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
unban_chat_member(user_id, **options)
|
|
306
|
+
|
|
307
|
+
Unbans a user.
|
|
308
|
+
|
|
309
|
+
```ruby
|
|
310
|
+
ctx.unban_chat_member(123456789)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
get_chat_administrators(**options)
|
|
314
|
+
|
|
315
|
+
Gets chat administrators.
|
|
316
|
+
|
|
317
|
+
```ruby
|
|
318
|
+
admins = ctx.get_chat_administrators
|
|
319
|
+
admins.each { |admin| puts admin.user.username }
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
get_chat_members_count(**options)
|
|
323
|
+
|
|
324
|
+
Gets chat member count.
|
|
325
|
+
|
|
326
|
+
```ruby
|
|
327
|
+
count = ctx.get_chat_members_count
|
|
328
|
+
ctx.reply("Chat has #{count} members")
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
get_chat(**options)
|
|
332
|
+
|
|
333
|
+
Gets chat information.
|
|
334
|
+
|
|
335
|
+
```ruby
|
|
336
|
+
chat_info = ctx.get_chat
|
|
337
|
+
ctx.reply("Chat title: #{chat_info['title']}")
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
Keyboard Helpers
|
|
341
|
+
|
|
342
|
+
keyboard(&block)
|
|
343
|
+
|
|
344
|
+
Creates a reply keyboard.
|
|
345
|
+
|
|
346
|
+
```ruby
|
|
347
|
+
kb = ctx.keyboard do
|
|
348
|
+
row "Button 1", "Button 2"
|
|
349
|
+
row request_location("Share Location")
|
|
350
|
+
end
|
|
351
|
+
ctx.reply("Choose:", reply_markup: kb)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
inline_keyboard(&block)
|
|
355
|
+
|
|
356
|
+
Creates an inline keyboard.
|
|
357
|
+
|
|
358
|
+
```ruby
|
|
359
|
+
kb = ctx.inline_keyboard do
|
|
360
|
+
row button "Visit", url: "https://example.com"
|
|
361
|
+
row button "Select", callback_data: "selected"
|
|
362
|
+
end
|
|
363
|
+
ctx.reply("Options:", reply_markup: kb)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
reply_with_keyboard(text, keyboard_markup, **options)
|
|
367
|
+
|
|
368
|
+
Sends a message with reply keyboard.
|
|
369
|
+
|
|
370
|
+
```ruby
|
|
371
|
+
keyboard = Telegem.keyboard { row "Yes", "No" }
|
|
372
|
+
ctx.reply_with_keyboard("Do you agree?", keyboard)
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
reply_with_inline_keyboard(text, inline_markup, **options)
|
|
376
|
+
|
|
377
|
+
Sends a message with inline keyboard.
|
|
378
|
+
|
|
379
|
+
```ruby
|
|
380
|
+
inline = Telegem.inline { row button "Click", callback_data: "click" }
|
|
381
|
+
ctx.reply_with_inline_keyboard("Click button:", inline)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
remove_keyboard(text = nil, **options)
|
|
385
|
+
|
|
386
|
+
Removes reply keyboard.
|
|
387
|
+
|
|
388
|
+
```ruby
|
|
389
|
+
ctx.remove_keyboard("Keyboard removed") # Sends message
|
|
390
|
+
# or
|
|
391
|
+
markup = ctx.remove_keyboard # Returns markup for later use
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
Scene Management
|
|
395
|
+
|
|
396
|
+
enter_scene(scene_name, **options)
|
|
397
|
+
|
|
398
|
+
Enters a scene (multi-step conversation).
|
|
399
|
+
|
|
400
|
+
```ruby
|
|
401
|
+
ctx.enter_scene(:survey)
|
|
402
|
+
ctx.enter_scene(:order, step: :select_product)
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
leave_scene(**options)
|
|
406
|
+
|
|
407
|
+
Leaves current scene.
|
|
408
|
+
|
|
409
|
+
```ruby
|
|
410
|
+
ctx.leave_scene
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
current_scene
|
|
414
|
+
|
|
415
|
+
Returns current scene object.
|
|
416
|
+
|
|
417
|
+
```ruby
|
|
418
|
+
scene = ctx.current_scene
|
|
419
|
+
ctx.reply("Current step: #{scene.current_step(ctx)}")
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Command Utilities
|
|
423
|
+
|
|
424
|
+
command?
|
|
425
|
+
|
|
426
|
+
Checks if current message is a command.
|
|
427
|
+
|
|
428
|
+
```ruby
|
|
429
|
+
if ctx.command?
|
|
430
|
+
ctx.reply("That's a command!")
|
|
431
|
+
end
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
command_args
|
|
435
|
+
|
|
436
|
+
Gets command arguments.
|
|
437
|
+
|
|
438
|
+
```ruby
|
|
439
|
+
# For "/greet John"
|
|
440
|
+
bot.command('greet') do |ctx|
|
|
441
|
+
name = ctx.command_args # => "John"
|
|
442
|
+
ctx.reply("Hello #{name}!")
|
|
443
|
+
end
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
Utility Methods
|
|
447
|
+
|
|
448
|
+
logger
|
|
449
|
+
|
|
450
|
+
Access bot logger.
|
|
451
|
+
|
|
452
|
+
```ruby
|
|
453
|
+
ctx.logger.info("Processing message from #{ctx.from.id}")
|
|
454
|
+
ctx.logger.error("Something went wrong!")
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
api
|
|
458
|
+
|
|
459
|
+
Access raw API client.
|
|
460
|
+
|
|
461
|
+
```ruby
|
|
462
|
+
# Direct API call
|
|
463
|
+
result = ctx.api.call!('getMe')
|
|
464
|
+
ctx.reply("Bot username: #{result['username']}")
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
user_id
|
|
468
|
+
|
|
469
|
+
Shortcut for user ID.
|
|
470
|
+
|
|
471
|
+
```ruby
|
|
472
|
+
user_id = ctx.user_id # Same as ctx.from.id
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
raw_update
|
|
476
|
+
|
|
477
|
+
Gets raw update data.
|
|
478
|
+
|
|
479
|
+
```ruby
|
|
480
|
+
update_json = ctx.raw_update.to_json
|
|
481
|
+
File.write('update.json', update_json)
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Complete Example
|
|
485
|
+
|
|
486
|
+
```ruby
|
|
487
|
+
bot.command('info') do |ctx|
|
|
488
|
+
# Show typing indicator
|
|
489
|
+
ctx.typing
|
|
490
|
+
|
|
491
|
+
# Gather info
|
|
492
|
+
user = ctx.from
|
|
493
|
+
chat = ctx.chat
|
|
494
|
+
|
|
495
|
+
# Create response
|
|
496
|
+
text = <<~INFO
|
|
497
|
+
👤 User Info:
|
|
498
|
+
ID: #{user.id}
|
|
499
|
+
Name: #{user.full_name}
|
|
500
|
+
Username: @#{user.username}
|
|
501
|
+
|
|
502
|
+
💬 Chat Info:
|
|
503
|
+
ID: #{chat.id}
|
|
504
|
+
Type: #{chat.type}
|
|
505
|
+
Title: #{chat.title}
|
|
506
|
+
|
|
507
|
+
📊 Members: #{ctx.get_chat_members_count}
|
|
508
|
+
INFO
|
|
509
|
+
|
|
510
|
+
# Send with inline keyboard
|
|
511
|
+
keyboard = ctx.inline_keyboard do
|
|
512
|
+
row button "Refresh", callback_data: "refresh_info"
|
|
513
|
+
row button "Close", callback_data: "close"
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
ctx.reply(text, reply_markup: keyboard)
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
# Handle refresh button
|
|
520
|
+
bot.on(:callback_query, data: "refresh_info") do |ctx|
|
|
521
|
+
ctx.answer_callback_query(text: "Refreshing...")
|
|
522
|
+
ctx.edit_message_text("Info refreshed at #{Time.now}")
|
|
523
|
+
end
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
Previous: Bot Methods | Next: Keyboard API
|
|
529
|
+
|
|
530
|
+
```
|
|
531
|
+
```
|