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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Test-Projects/Movie-tracker-bot/Gemfile +2 -0
  3. data/Test-Projects/Movie-tracker-bot/bot.rb +62 -0
  4. data/Test-Projects/Movie-tracker-bot/handlers/.gitkeep +0 -0
  5. data/Test-Projects/Movie-tracker-bot/handlers/add_1_.rb +160 -0
  6. data/Test-Projects/Movie-tracker-bot/handlers/add_2_.rb +139 -0
  7. data/Test-Projects/Movie-tracker-bot/handlers/premium.rb +13 -0
  8. data/Test-Projects/Movie-tracker-bot/handlers/report.rb +31 -0
  9. data/Test-Projects/Movie-tracker-bot/handlers/search.rb +150 -0
  10. data/Test-Projects/Movie-tracker-bot/handlers/sponsor.rb +14 -0
  11. data/Test-Projects/Movie-tracker-bot/handlers/start.rb +48 -0
  12. data/Test-Projects/Movie-tracker-bot/handlers/watch.rb +210 -0
  13. data/Test-Projects/Test-submitted-by-marvel/.gitkeep +0 -0
  14. data/Test-Projects/Test-submitted-by-marvel/Marvel-bot.md +3 -0
  15. data/docs-src/.gitkeep +0 -0
  16. data/docs-src/Bot-registration_.PNG +0 -0
  17. data/docs-src/bot.md +295 -0
  18. data/docs-src/context|ctx|.md +531 -0
  19. data/docs-src/getting-started.md +328 -0
  20. data/docs-src/keyboard_inline.md +413 -0
  21. data/docs-src/scene.md +509 -0
  22. data/docs-src/understanding-ctx.md +581 -0
  23. data/lib/api/client.rb +17 -16
  24. data/lib/core/bot.rb +19 -25
  25. data/lib/telegem.rb +1 -1
  26. data/lib/webhook/server.rb +1 -1
  27. metadata +26 -15
  28. data/docs/Api.md +0 -211
  29. data/docs/Cookbook(copy_paste).md +0 -644
  30. data/docs/Getting_started.md +0 -348
  31. data/docs/How_to_use.md +0 -571
  32. data/docs/QuickStart.md +0 -258
  33. data/docs/Understanding_Scene.md +0 -434
  34. data/docs/Usage.md +0 -717
  35. data/docs/webhook_setup.md +0 -199
  36. /data/{docs → Test-Projects/Movie-tracker-bot}/.gitkeep +0 -0
@@ -1,644 +0,0 @@
1
-
2
- # 🍳 Telegem Cookbook
3
-
4
- Quick copy-paste recipes for common bot tasks. When you think "How do I...", find your answer here and just paste!
5
-
6
- **Join for help & updates:** [![Official Channel](https://img.shields.io/badge/🚀-t.me/telegem__me2-blue?style=flat&logo=telegram)](https://t.me/telegem_me2)
7
-
8
- ---
9
-
10
- ## 📋 Table of Contents
11
- - [Basic Setup](#-basic-setup)
12
- - [Message Handling](#-message-handling)
13
- - [Keyboards & Buttons](#-keyboards--buttons)
14
- - [Files & Media](#-files--media)
15
- - [User Management](#-user-management)
16
- - [Scenes & Multi-step](#-scenes--multi-step)
17
- - [Utility Patterns](#-utility-patterns)
18
- - [Error Handling](#-error-handling)
19
- - [Deployment](#-deployment)
20
-
21
- ---
22
-
23
- ## 🤖 Basic Setup
24
-
25
- ### Minimal Echo Bot
26
- ```ruby
27
- require 'telegem'
28
- bot = Telegem.new("YOUR_TOKEN")
29
- bot.on(:message) { |ctx| ctx.reply("You said: #{ctx.message.text}") }
30
- bot.start_polling
31
- # Save as bot.rb and run: ruby bot.rb
32
- ```
33
-
34
- Webhook Setup (Production)
35
-
36
- ```ruby
37
- require 'telegem'
38
- bot = Telegem.new(ENV['TELEGRAM_BOT_TOKEN'])
39
- bot.on(:message) { |ctx| ctx.reply("Hello from webhook!") }
40
- Telegem.webhook(bot) # One-liner for production
41
- ```
42
-
43
- ---
44
-
45
- 📨 Message Handling
46
-
47
- Command with Arguments
48
-
49
- ```ruby
50
- bot.command("search") do |ctx|
51
- query = ctx.message.command_args # "ruby programming" from "/search ruby programming"
52
- ctx.reply("Searching for: #{query}") if query
53
- end
54
- ```
55
-
56
- Handle Specific Text
57
-
58
- ```ruby
59
- # Exact match
60
- bot.on(:message, text: "ping") { |ctx| ctx.reply("pong!") }
61
-
62
- # Regex match (case-insensitive)
63
- bot.hears(/hello|hi|hey/i) { |ctx| ctx.reply("Greetings! 👋") }
64
-
65
- # Contains word
66
- bot.on(:message) do |ctx|
67
- if ctx.message.text&.include?("bot")
68
- ctx.reply("You mentioned me! 🤖")
69
- end
70
- end
71
- ```
72
-
73
- Reply to Specific Message
74
-
75
- ```ruby
76
- bot.on(:message) do |ctx|
77
- # Reply to the user's message
78
- ctx.reply("Got it!", reply_to_message_id: ctx.message.message_id)
79
- end
80
- ```
81
-
82
- Different Chat Types
83
-
84
- ```ruby
85
- bot.on(:message) do |ctx|
86
- case ctx.chat.type
87
- when "private"
88
- ctx.reply("Private chat 👤")
89
- when "group", "supergroup"
90
- ctx.reply("Group chat 👥")
91
- when "channel"
92
- ctx.reply("Channel 📢")
93
- end
94
- end
95
- ```
96
-
97
- ---
98
-
99
- ⌨️ Keyboards & Buttons
100
-
101
- Simple Menu Keyboard
102
-
103
- ```ruby
104
- bot.command("menu") do |ctx|
105
- keyboard = Telegem.keyboard do
106
- row "🍕 Order Food", "🛍️ Shop"
107
- row "ℹ️ Help", "⚙️ Settings"
108
- resize true # Fits screen
109
- one_time true # Hides after use
110
- end
111
- ctx.reply("Main Menu:", reply_markup: keyboard)
112
- end
113
- ```
114
-
115
- Inline Buttons with Callback
116
-
117
- ```ruby
118
- bot.command("vote") do |ctx|
119
- keyboard = Telegem.inline do
120
- row do
121
- callback "👍 Yes", "vote_yes"
122
- callback "👎 No", "vote_no"
123
- end
124
- end
125
- ctx.reply("Do you like Ruby?", reply_markup: keyboard)
126
- end
127
-
128
- # Handle button clicks
129
- bot.on(:callback_query) do |ctx|
130
- case ctx.data
131
- when "vote_yes"
132
- ctx.answer_callback_query(text: "You voted Yes! 🎉")
133
- ctx.edit_message_text("✅ Thanks for voting Yes!")
134
- when "vote_no"
135
- ctx.answer_callback_query(text: "You voted No 😢", show_alert: true)
136
- ctx.edit_message_text("❌ You voted No")
137
- end
138
- end
139
- ```
140
-
141
- URL & Web App Buttons
142
-
143
- ```ruby
144
- bot.command("links") do |ctx|
145
- keyboard = Telegem.inline do
146
- row do
147
- url "🌐 Website", "https://gitlab.com/ruby-telegem/telegem"
148
- url "📚 Docs", "https://core.telegram.org/bots/api"
149
- end
150
- row do
151
- web_app "📱 Open App", "https://yourapp.com"
152
- end
153
- end
154
- ctx.reply("Useful links:", reply_markup: keyboard)
155
- end
156
- ```
157
-
158
- Remove Keyboard
159
-
160
- ```ruby
161
- bot.command("hide") do |ctx|
162
- ctx.reply("Keyboard hidden!", reply_markup: Telegem.remove_keyboard)
163
- end
164
- ```
165
-
166
- Request Contact/Location
167
-
168
- ```ruby
169
- bot.command("share") do |ctx|
170
- keyboard = Telegem.keyboard do
171
- row do
172
- button "📱 Share Contact", request_contact: true
173
- button "📍 Share Location", request_location: true
174
- end
175
- end
176
- ctx.reply("Please share:", reply_markup: keyboard)
177
- end
178
-
179
- # Handle received contact
180
- bot.on(:message) do |ctx|
181
- if ctx.message.contact
182
- phone = ctx.message.contact.phone_number
183
- ctx.reply("Thanks! I got your number: #{phone}")
184
- elsif ctx.message.location
185
- lat = ctx.message.location.latitude
186
- lon = ctx.message.location.longitude
187
- ctx.reply("Location received: #{lat}, #{lon}")
188
- end
189
- end
190
- ```
191
-
192
- ---
193
-
194
- 📁 Files & Media
195
-
196
- Send Photo from File
197
-
198
- ```ruby
199
- bot.command("cat") do |ctx|
200
- ctx.photo("path/to/cat.jpg", caption: "Here's a cute cat! 🐱")
201
- end
202
- ```
203
-
204
- Send Photo from URL
205
-
206
- ```ruby
207
- bot.command("meme") do |ctx|
208
- ctx.photo("https://api.memegen.com/images/buzz/memes/meme.jpg",
209
- caption: "Random meme!")
210
- end
211
- ```
212
-
213
- Send Document
214
-
215
- ```ruby
216
- bot.command("report") do |ctx|
217
- ctx.document("monthly_report.pdf",
218
- caption: "Monthly Report 📊",
219
- filename: "report_2024.pdf") # Custom filename
220
- end
221
- ```
222
-
223
- Send Multiple Photos as Album
224
-
225
- ```ruby
226
- bot.command("album") do |ctx|
227
- # Note: Telegram groups media with same media_group_id
228
- ctx.photo("photo1.jpg", caption: "First photo", media_group_id: "album_123")
229
- ctx.photo("photo2.jpg", caption: "Second photo", media_group_id: "album_123")
230
- end
231
- ```
232
-
233
- Show "Typing" Indicator
234
-
235
- ```ruby
236
- bot.command("process") do |ctx|
237
- ctx.typing # Shows "typing..." for 5 seconds
238
- sleep 3 # Simulate work
239
- ctx.reply("Processing complete!")
240
- end
241
-
242
- # Or use the helper for longer operations
243
- bot.command("analyze") do |ctx|
244
- ctx.with_typing do
245
- # Your processing code here
246
- result = complex_analysis(ctx.message.text)
247
- ctx.reply("Analysis: #{result}")
248
- end
249
- end
250
- ```
251
-
252
- ---
253
-
254
- 👥 User Management
255
-
256
- Welcome New Members
257
-
258
- ```ruby
259
- bot.on(:message) do |ctx|
260
- if ctx.message.new_chat_members
261
- ctx.message.new_chat_members.each do |user|
262
- ctx.reply("Welcome #{user.full_name} to the group! 🎉")
263
- end
264
- end
265
- end
266
- ```
267
-
268
- Detect User Left
269
-
270
- ```ruby
271
- bot.on(:message) do |ctx|
272
- if ctx.message.left_chat_member
273
- ctx.reply("#{ctx.message.left_chat_member.full_name} left the group 👋")
274
- end
275
- end
276
- ```
277
-
278
- Basic Admin Commands
279
-
280
- ```ruby
281
- # Only works if your bot is admin
282
- bot.command("ban") do |ctx|
283
- if ctx.message.reply_to_message
284
- user_id = ctx.message.reply_to_message.from.id
285
- ctx.ban_chat_member(user_id)
286
- ctx.reply("User banned 🚫")
287
- else
288
- ctx.reply("Reply to a message to ban the user")
289
- end
290
- end
291
-
292
- bot.command("unban") do |ctx|
293
- args = ctx.message.command_args
294
- if args && args.match?(/\d+/)
295
- ctx.unban_chat_member(args.to_i)
296
- ctx.reply("User unbanned ✅")
297
- end
298
- end
299
-
300
- bot.command("pin") do |ctx|
301
- if ctx.message.reply_to_message
302
- ctx.pin_message(ctx.message.reply_to_message.message_id)
303
- ctx.reply("Message pinned 📌")
304
- end
305
- end
306
- ```
307
-
308
- User Cooldown / Rate Limit
309
-
310
- ```ruby
311
- # Using session for simple rate limiting
312
- bot.on(:message) do |ctx|
313
- user_id = ctx.from.id
314
- last_time = ctx.session[:last_message_time] || 0
315
-
316
- if Time.now.to_i - last_time < 2 # 2 seconds cooldown
317
- ctx.reply("Please wait a moment... ⏳")
318
- else
319
- ctx.session[:last_message_time] = Time.now.to_i
320
- # Process message normally
321
- ctx.reply("Message received!")
322
- end
323
- end
324
- ```
325
-
326
- ---
327
-
328
- 🎭 Scenes & Multi-step
329
-
330
- Simple Registration Flow
331
-
332
- ```ruby
333
- bot.scene("signup") do
334
- step :ask_name do |ctx|
335
- ctx.reply("What's your name?")
336
- next_step :ask_email
337
- end
338
-
339
- step :ask_email do |ctx|
340
- ctx.state[:name] = ctx.message.text
341
- ctx.reply("Great #{ctx.state[:name]}! Now enter your email:")
342
- next_step :confirm
343
- end
344
-
345
- step :confirm do |ctx|
346
- ctx.state[:email] = ctx.message.text
347
-
348
- keyboard = Telegem.inline do
349
- row do
350
- callback "✅ Confirm", "confirm_signup"
351
- callback "🔄 Restart", "restart_signup"
352
- end
353
- end
354
-
355
- ctx.reply("Confirm details:\nName: #{ctx.state[:name]}\nEmail: #{ctx.state[:email]}",
356
- reply_markup: keyboard)
357
- end
358
-
359
- on_enter do |ctx|
360
- ctx.reply("Starting registration... ✨")
361
- ctx.state.clear # Reset temp storage
362
- end
363
-
364
- on_leave do |ctx|
365
- ctx.reply("Registration complete! 🎉")
366
- end
367
- end
368
-
369
- # Start the scene
370
- bot.command("register") { |ctx| ctx.enter_scene("signup") }
371
-
372
- # Handle scene callbacks
373
- bot.on(:callback_query) do |ctx|
374
- case ctx.data
375
- when "confirm_signup"
376
- ctx.answer_callback_query(text: "Account created!")
377
- # Save to database here
378
- ctx.leave_scene
379
- when "restart_signup"
380
- ctx.answer_callback_query(text: "Starting over...")
381
- ctx.enter_scene("signup") # Re-enter scene
382
- end
383
- end
384
- ```
385
-
386
- Shopping Cart Scene
387
-
388
- ```ruby
389
- bot.scene("cart") do
390
- step :show_products do |ctx|
391
- products = ["🍎 Apple $1", "🍌 Banana $2", "🍊 Orange $3"]
392
- keyboard = Telegem.inline do
393
- products.each do |product|
394
- row { callback product, "add_#{product.split.first.downcase}" }
395
- end
396
- row { callback "🛒 Checkout", "checkout" }
397
- end
398
- ctx.reply("Select products:", reply_markup: keyboard)
399
- next_step :handle_selection
400
- end
401
-
402
- step :handle_selection do |ctx|
403
- if ctx.callback_query
404
- if ctx.data.start_with?("add_")
405
- item = ctx.data.sub("add_", "")
406
- ctx.session[:cart] ||= []
407
- ctx.session[:cart] << item
408
- ctx.answer_callback_query(text: "Added #{item} to cart!")
409
- elsif ctx.data == "checkout"
410
- ctx.reply("Your cart: #{ctx.session[:cart].join(', ')}")
411
- ctx.leave_scene
412
- end
413
- end
414
- # Stay in same step
415
- step :show_products
416
- end
417
- end
418
-
419
- bot.command("shop") { |ctx| ctx.enter_scene("cart") }
420
- ```
421
-
422
- ---
423
-
424
- 🛠️ Utility Patterns
425
-
426
- Logging Middleware
427
-
428
- ```ruby
429
- bot.use do |ctx, next_handler|
430
- puts "[#{Time.now}] #{ctx.from.username}: #{ctx.message&.text || ctx.callback_query&.data}"
431
- next_handler.call(ctx)
432
- end
433
- ```
434
-
435
- Authentication Middleware
436
-
437
- ```ruby
438
- ADMIN_IDS = [123456789, 987654321] # Your user IDs
439
-
440
- class AdminOnly
441
- def call(ctx, next_handler)
442
- if ADMIN_IDS.include?(ctx.from.id)
443
- next_handler.call(ctx)
444
- else
445
- ctx.reply("🚫 Admin only!")
446
- end
447
- end
448
- end
449
-
450
- bot.use(AdminOnly.new)
451
-
452
- # Or use inline
453
- bot.use do |ctx, next_handler|
454
- if ctx.from.username == "slick_phantom"
455
- next_handler.call(ctx)
456
- else
457
- ctx.reply("You're not slick_phantom! 🤨")
458
- end
459
- end
460
- ```
461
-
462
- User Session Data
463
-
464
- ```ruby
465
- # Store user preferences
466
- bot.command("setlang") do |ctx|
467
- lang = ctx.message.command_args
468
- ctx.session[:language] = lang if ["en", "es", "fr"].include?(lang)
469
- ctx.reply("Language set to #{lang}")
470
- end
471
-
472
- bot.command("profile") do |ctx|
473
- lang = ctx.session[:language] || "en"
474
- theme = ctx.session[:theme] || "light"
475
- ctx.reply("Your settings:\nLanguage: #{lang}\nTheme: #{theme}")
476
- end
477
- ```
478
-
479
- Broadcast to All Users
480
-
481
- ```ruby
482
- # Store user IDs when they start the bot
483
- bot.command("start") do |ctx|
484
- user_id = ctx.from.id
485
- # In production, save to database instead of global variable
486
- $users ||= []
487
- $users << user_id unless $users.include?(user_id)
488
- ctx.reply("Welcome!")
489
- end
490
-
491
- # Admin command to broadcast
492
- bot.command("broadcast") do |ctx|
493
- if ADMIN_IDS.include?(ctx.from.id)
494
- message = ctx.message.command_args
495
- $users.each do |user_id|
496
- begin
497
- ctx.api.call("sendMessage", chat_id: user_id, text: message)
498
- sleep 0.1 # Be nice to Telegram's rate limits
499
- rescue => e
500
- puts "Failed to send to #{user_id}: #{e.message}"
501
- end
502
- end
503
- ctx.reply("Broadcast sent to #{$users.size} users")
504
- end
505
- end
506
- ```
507
-
508
- Command Aliases
509
-
510
- ```ruby
511
- # Multiple commands for same action
512
- ["start", "hello", "hi"].each do |cmd|
513
- bot.command(cmd) do |ctx|
514
- ctx.reply("Welcome to the bot! Use /help for commands.")
515
- end
516
- end
517
- ```
518
-
519
- ---
520
-
521
- 🚨 Error Handling
522
-
523
- Global Error Handler
524
-
525
- ```ruby
526
- bot.error do |error, ctx|
527
- ctx&.reply("❌ Something went wrong! Our developers have been notified.")
528
- puts "ERROR: #{error.class}: #{error.message}"
529
- puts error.backtrace if error.backtrace
530
- # Send to error tracking service (e.g., Sentry)
531
- end
532
- ```
533
-
534
- Safe File Operations
535
-
536
- ```ruby
537
- bot.command("getfile") do |ctx|
538
- begin
539
- if File.exist?("data.txt")
540
- ctx.document(File.open("data.txt"))
541
- else
542
- ctx.reply("File not found")
543
- end
544
- rescue => e
545
- ctx.reply("Error reading file: #{e.message}")
546
- end
547
- end
548
- ```
549
-
550
- API Error Handling
551
-
552
- ```ruby
553
- bot.on(:message) do |ctx|
554
- begin
555
- response = ctx.reply("Processing...")
556
- # response is an HTTPX request object
557
- response.wait
558
- if response.error
559
- ctx.reply("Telegram API error: #{response.error.message}")
560
- end
561
- rescue Telegem::API::NetworkError => e
562
- ctx.reply("Network issue: #{e.message}")
563
- rescue => e
564
- ctx.reply("Unexpected error")
565
- end
566
- end
567
- ```
568
-
569
- ---
570
-
571
- ☁️ Deployment
572
-
573
- Render.com Deployment Files
574
-
575
- bot.rb
576
-
577
- ```ruby
578
- require 'telegem'
579
-
580
- bot = Telegem.new(ENV['TELEGRAM_BOT_TOKEN'])
581
-
582
- # Your bot logic here
583
- bot.command("start") { |ctx| ctx.reply("Bot is live on Render! ☁️") }
584
- bot.on(:message) { |ctx| ctx.reply("Echo: #{ctx.message.text}") }
585
-
586
- # Auto-start webhook in production
587
- if ENV['RACK_ENV'] == 'production'
588
- Telegem.webhook(bot)
589
- else
590
- bot.start_polling # For local development
591
- end
592
- ```
593
-
594
- Gemfile
595
-
596
- ```ruby
597
- source 'https://rubygems.org'
598
- gem 'telegem'
599
- ```
600
-
601
- config.ru (Required for Render)
602
-
603
- ```ruby
604
- require './bot'
605
- run ->(env) { [200, {}, ['Telegem Bot Server']] }
606
- ```
607
-
608
- Environment Variables Template (.env.local)
609
-
610
- ```bash
611
- TELEGRAM_BOT_TOKEN=123456:ABCdefGHIjklMNOpqrsTUVwxyz
612
- TELEGRAM_SECRET_TOKEN= # Auto-generated if not set
613
- PORT=3000
614
- RACK_ENV=production
615
- ```
616
-
617
- Health Check Endpoint (For Cloud Platforms)
618
-
619
- ```ruby
620
- # Add to your bot.rb for platforms that require /health
621
- require 'rack'
622
- app = Rack::Builder.new do
623
- map "/health" do
624
- run ->(env) { [200, {}, [{ status: "ok", bot: "running" }.to_json]] }
625
- end
626
- # ... rest of your app
627
- end
628
- ```
629
-
630
- ---
631
-
632
- 🎯 Pro Tips
633
-
634
- 1. Use .env files for local development with the dotenv gem
635
- 2. Store user data in a database (SQLite, PostgreSQL) instead of memory for persistence
636
- 3. Respect rate limits: Add small delays (sleep 0.1) when sending many messages
637
- 4. Use ctx.with_typing for operations longer than 1-2 seconds
638
- 5. Test with multiple users using Telegram's @BotFather test feature
639
-
640
- ---
641
-
642
- Need more recipes? Join our community and ask! https://img.shields.io/badge/🍳-t.me/telegem__me2-blue?style=flat&logo=telegram
643
-
644
- Copy. Paste. Ship. 🚀