telegem 3.0.6 โ 3.1.3
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/CHANGELOG +92 -12
- data/CODE_OF_CONDUCT.md +13 -0
- data/Contributing.md +125 -517
- data/Readme.md +10 -61
- data/Starts_HallofFame.md +27 -21
- data/lib/api/client.rb +63 -56
- data/lib/core/bot.rb +32 -22
- data/lib/core/context.rb +47 -18
- data/lib/core/rate_limit.rb +100 -0
- data/lib/core/scene.rb +110 -43
- data/lib/plugins/file_extract.rb +97 -0
- data/lib/session/scene_middleware.rb +22 -0
- data/lib/telegem.rb +3 -1
- metadata +26 -84
- data/docs-src/Bot-registration_.PNG +0 -0
- data/docs-src/bot.md +0 -464
- data/docs-src/context|ctx|.md +0 -531
- data/docs-src/ctx.md +0 -399
- data/docs-src/getting-started.md +0 -328
- data/docs-src/keyboard_inline.md +0 -413
- data/docs-src/scene.md +0 -509
- data/docs-src/webhook.md +0 -341
- /data/{docs-src โ lib/plugins}/.gitkeep +0 -0
data/docs-src/ctx.md
DELETED
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
.md - Your Gateway to Telegram Bot Mastery
|
|
2
|
-
|
|
3
|
-
๐ What is ctx?
|
|
4
|
-
|
|
5
|
-
Imagine you're at a coffee shop. The barista (ctx) is your connection to everything:
|
|
6
|
-
|
|
7
|
-
ยท Takes your order (message)
|
|
8
|
-
ยท Knows who you are (user info)
|
|
9
|
-
ยท Has your table number (chat info)
|
|
10
|
-
ยท Can bring you coffee (send replies)
|
|
11
|
-
ยท Remembers your usual (session data)
|
|
12
|
-
|
|
13
|
-
ctx is your barista for Telegram bots.
|
|
14
|
-
|
|
15
|
-
๐ฏ The 5 Essential Things ctx Gives You
|
|
16
|
-
|
|
17
|
-
1. Who's Talking? (ctx.from)
|
|
18
|
-
|
|
19
|
-
```ruby
|
|
20
|
-
# Every person has an ID card
|
|
21
|
-
user_id = ctx.from.id # Like a social security number (unique!)
|
|
22
|
-
username = ctx.from.username # @username (might be nil)
|
|
23
|
-
name = ctx.from.first_name # "John"
|
|
24
|
-
full_name = ctx.from.full_name # "John Doe" (first + last)
|
|
25
|
-
|
|
26
|
-
# Quick check:
|
|
27
|
-
if ctx.from.is_bot
|
|
28
|
-
ctx.reply("Hey fellow bot! ๐ค")
|
|
29
|
-
end
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
2. Where Are We? (ctx.chat)
|
|
33
|
-
|
|
34
|
-
```ruby
|
|
35
|
-
chat_id = ctx.chat.id # Room number
|
|
36
|
-
room_type = ctx.chat.type # "private", "group", "supergroup", "channel"
|
|
37
|
-
|
|
38
|
-
# Different rooms, different rules:
|
|
39
|
-
case ctx.chat.type
|
|
40
|
-
when "private"
|
|
41
|
-
ctx.reply("Just us talking! ๐คซ")
|
|
42
|
-
when "group"
|
|
43
|
-
ctx.reply("Hello everyone in the group! ๐")
|
|
44
|
-
end
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
3. What Was Said? (ctx.message)
|
|
48
|
-
|
|
49
|
-
```ruby
|
|
50
|
-
# The actual message
|
|
51
|
-
text = ctx.message.text # What they typed
|
|
52
|
-
msg_id = ctx.message.message_id # Message ID (for editing/deleting)
|
|
53
|
-
|
|
54
|
-
# Was it a photo?
|
|
55
|
-
if ctx.message.photo
|
|
56
|
-
ctx.reply("Nice photo! ๐ธ")
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# Was it a location?
|
|
60
|
-
if ctx.message.location
|
|
61
|
-
lat = ctx.message.location.latitude
|
|
62
|
-
lng = ctx.message.location.longitude
|
|
63
|
-
ctx.reply("You're at #{lat}, #{lng}")
|
|
64
|
-
end
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
4. Did They Click a Button? (ctx.data)
|
|
68
|
-
|
|
69
|
-
```ruby
|
|
70
|
-
# Only works for inline button clicks
|
|
71
|
-
bot.on(:callback_query) do |ctx|
|
|
72
|
-
# ctx.data contains what you put in callback_data
|
|
73
|
-
case ctx.data
|
|
74
|
-
when "pizza"
|
|
75
|
-
ctx.reply("๐ Pizza ordered!")
|
|
76
|
-
when "burger"
|
|
77
|
-
ctx.reply("๐ Burger coming up!")
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# ALWAYS answer callback queries!
|
|
81
|
-
ctx.answer_callback_query(text: "Done!")
|
|
82
|
-
end
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
5. Remember Stuff (ctx.session & ctx.state)
|
|
86
|
-
|
|
87
|
-
```ruby
|
|
88
|
-
# ctx.session = Long-term memory (survives restarts)
|
|
89
|
-
ctx.session[:language] = "en" # User prefers English
|
|
90
|
-
ctx.session[:pizza_count] ||= 0 # Start at 0, then increment
|
|
91
|
-
ctx.session[:pizza_count] += 1
|
|
92
|
-
|
|
93
|
-
# ctx.state = Short-term memory (current conversation)
|
|
94
|
-
ctx.state[:asking_for_name] = true # Just for this flow
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
๐ Your First 5 Minutes with ctx
|
|
98
|
-
|
|
99
|
-
Minute 1: Echo Bot
|
|
100
|
-
|
|
101
|
-
```ruby
|
|
102
|
-
bot.on(:message) do |ctx|
|
|
103
|
-
# Whatever user says, repeat it back
|
|
104
|
-
ctx.reply("You said: #{ctx.message.text}")
|
|
105
|
-
end
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
Minute 2: Welcome Bot
|
|
109
|
-
|
|
110
|
-
```ruby
|
|
111
|
-
bot.command('start') do |ctx|
|
|
112
|
-
ctx.reply("Welcome #{ctx.from.first_name}! ๐")
|
|
113
|
-
ctx.reply("Your ID: #{ctx.from.id}")
|
|
114
|
-
ctx.reply("Chat ID: #{ctx.chat.id}")
|
|
115
|
-
end
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
Minute 3: Memory Bot
|
|
119
|
-
|
|
120
|
-
```ruby
|
|
121
|
-
bot.command('count') do |ctx|
|
|
122
|
-
# Count how many times user used /count
|
|
123
|
-
ctx.session[:count] ||= 0
|
|
124
|
-
ctx.session[:count] += 1
|
|
125
|
-
ctx.reply("You've counted #{ctx.session[:count]} times!")
|
|
126
|
-
end
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Minute 4: Smart Bot
|
|
130
|
-
|
|
131
|
-
```ruby
|
|
132
|
-
bot.hears(/hello|hi|hey/i) do |ctx|
|
|
133
|
-
if ctx.chat.type == "private"
|
|
134
|
-
ctx.reply("Hello there! ๐")
|
|
135
|
-
else
|
|
136
|
-
ctx.reply("Hello #{ctx.from.first_name}! ๐")
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Minute 5: Media Bot
|
|
142
|
-
|
|
143
|
-
```ruby
|
|
144
|
-
bot.command('cat') do |ctx|
|
|
145
|
-
ctx.reply("Here's a cat! ๐ฑ")
|
|
146
|
-
ctx.photo("https://cataas.com/cat", caption: "Random cat!")
|
|
147
|
-
end
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
๐ฆ The ctx Toolbox (25+ Methods)
|
|
151
|
-
|
|
152
|
-
Sending Messages
|
|
153
|
-
|
|
154
|
-
```ruby
|
|
155
|
-
# Text messages
|
|
156
|
-
ctx.reply("Hello!") # Basic
|
|
157
|
-
ctx.reply("*Bold text*", parse_mode: "Markdown") # Formatted
|
|
158
|
-
ctx.reply("<b>HTML bold</b>", parse_mode: "HTML") # HTML
|
|
159
|
-
|
|
160
|
-
# Replying to specific message
|
|
161
|
-
ctx.reply("Answering this", reply_to_message_id: 123)
|
|
162
|
-
|
|
163
|
-
# With keyboard at bottom
|
|
164
|
-
keyboard = Telegem.keyboard { row "Yes", "No" }
|
|
165
|
-
ctx.reply("Choose:", reply_markup: keyboard)
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Sending Files & Media
|
|
169
|
-
|
|
170
|
-
```ruby
|
|
171
|
-
# Photo (from URL, file, or file_id)
|
|
172
|
-
ctx.photo("https://example.com/cat.jpg")
|
|
173
|
-
ctx.photo(File.open("cat.jpg"))
|
|
174
|
-
ctx.photo("AgACAx...") # Telegram file_id
|
|
175
|
-
|
|
176
|
-
# With caption
|
|
177
|
-
ctx.photo("cat.jpg", caption: "My cat! ๐ฑ")
|
|
178
|
-
|
|
179
|
-
# Document (PDF, etc.)
|
|
180
|
-
ctx.document("report.pdf", caption: "Monthly report")
|
|
181
|
-
|
|
182
|
-
# Audio, Video, Voice
|
|
183
|
-
ctx.audio("song.mp3", caption: "My song")
|
|
184
|
-
ctx.video("clip.mp4", caption: "Funny video!")
|
|
185
|
-
ctx.voice("message.ogg", caption: "Voice note")
|
|
186
|
-
|
|
187
|
-
# Location
|
|
188
|
-
ctx.location(51.5074, -0.1278) # London coordinates
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
Managing Messages
|
|
192
|
-
|
|
193
|
-
```ruby
|
|
194
|
-
# Edit a message (need its message_id)
|
|
195
|
-
ctx.edit_message_text("Updated text!", message_id: 123)
|
|
196
|
-
|
|
197
|
-
# Delete messages
|
|
198
|
-
ctx.delete_message # Current message
|
|
199
|
-
ctx.delete_message(123) # Specific message
|
|
200
|
-
|
|
201
|
-
# Forward/Copy messages
|
|
202
|
-
ctx.forward_message(source_chat_id, message_id)
|
|
203
|
-
ctx.copy_message(source_chat_id, message_id)
|
|
204
|
-
|
|
205
|
-
# Pin/Unpin
|
|
206
|
-
ctx.pin_message(message_id)
|
|
207
|
-
ctx.unpin_message
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
Interactive Features
|
|
211
|
-
|
|
212
|
-
```ruby
|
|
213
|
-
# Show "typing..." indicator
|
|
214
|
-
ctx.typing
|
|
215
|
-
# or
|
|
216
|
-
ctx.with_typing do
|
|
217
|
-
# Long operation here
|
|
218
|
-
sleep 2
|
|
219
|
-
ctx.reply("Done thinking!")
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
# Show other actions
|
|
223
|
-
ctx.uploading_photo # "uploading photo..."
|
|
224
|
-
ctx.uploading_document # "uploading document..."
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
Group Management (Bot needs admin)
|
|
228
|
-
|
|
229
|
-
```ruby
|
|
230
|
-
ctx.kick_chat_member(user_id) # Remove from group
|
|
231
|
-
ctx.ban_chat_member(user_id) # Ban user
|
|
232
|
-
ctx.unban_chat_member(user_id) # Unban user
|
|
233
|
-
|
|
234
|
-
# Get info
|
|
235
|
-
admins = ctx.get_chat_administrators
|
|
236
|
-
member_count = ctx.get_chat_members_count
|
|
237
|
-
chat_info = ctx.get_chat
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
๐ญ Real-World Scenarios
|
|
241
|
-
|
|
242
|
-
Scenario 1: Pizza Order
|
|
243
|
-
|
|
244
|
-
```ruby
|
|
245
|
-
bot.command('order') do |ctx|
|
|
246
|
-
# Step 1: Ask for pizza type
|
|
247
|
-
keyboard = ctx.keyboard do
|
|
248
|
-
row "Margherita", "Pepperoni"
|
|
249
|
-
row "Veggie", "Cancel"
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
ctx.reply("Choose pizza:", reply_markup: keyboard)
|
|
253
|
-
ctx.state[:step] = "waiting_for_pizza"
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
# Handle the choice
|
|
257
|
-
bot.hears("Margherita") do |ctx|
|
|
258
|
-
if ctx.state[:step] == "waiting_for_pizza"
|
|
259
|
-
ctx.reply("๐ Margherita selected!")
|
|
260
|
-
ctx.reply("What's your address?")
|
|
261
|
-
ctx.state[:step] = "waiting_for_address"
|
|
262
|
-
end
|
|
263
|
-
end
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
Scenario 2: Quiz Game
|
|
267
|
-
|
|
268
|
-
```ruby
|
|
269
|
-
bot.command('quiz') do |ctx|
|
|
270
|
-
ctx.session[:score] ||= 0
|
|
271
|
-
|
|
272
|
-
inline = ctx.inline_keyboard do
|
|
273
|
-
row button "Paris", callback_data: "answer_paris"
|
|
274
|
-
row button "London", callback_data: "answer_london"
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
ctx.reply("Capital of France?", reply_markup: inline)
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
bot.on(:callback_query) do |ctx|
|
|
281
|
-
if ctx.data == "answer_paris"
|
|
282
|
-
ctx.session[:score] += 1
|
|
283
|
-
ctx.answer_callback_query(text: "โ
Correct!")
|
|
284
|
-
ctx.edit_message_text("๐ Correct! Score: #{ctx.session[:score]}")
|
|
285
|
-
else
|
|
286
|
-
ctx.answer_callback_query(text: "โ Wrong!")
|
|
287
|
-
end
|
|
288
|
-
end
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Scenario 3: Support Ticket
|
|
292
|
-
|
|
293
|
-
```ruby
|
|
294
|
-
bot.command('support') do |ctx|
|
|
295
|
-
ctx.reply("Describe your issue:")
|
|
296
|
-
ctx.state[:collecting_issue] = true
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
bot.on(:message) do |ctx|
|
|
300
|
-
if ctx.state[:collecting_issue]
|
|
301
|
-
issue = ctx.message.text
|
|
302
|
-
# Save to database...
|
|
303
|
-
ctx.reply("Ticket created! We'll contact you.")
|
|
304
|
-
ctx.state.delete(:collecting_issue)
|
|
305
|
-
end
|
|
306
|
-
end
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
โ ๏ธ Common Mistakes & Fixes
|
|
310
|
-
|
|
311
|
-
Mistake 1: Assuming ctx.message always exists
|
|
312
|
-
|
|
313
|
-
```ruby
|
|
314
|
-
# โ WRONG
|
|
315
|
-
puts ctx.message.text # Crashes if not a message update!
|
|
316
|
-
|
|
317
|
-
# โ
RIGHT
|
|
318
|
-
if ctx.message && ctx.message.text
|
|
319
|
-
puts ctx.message.text
|
|
320
|
-
end
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
Mistake 2: Forgetting to answer callbacks
|
|
324
|
-
|
|
325
|
-
```ruby
|
|
326
|
-
# โ WRONG (Telegram will show "loading...")
|
|
327
|
-
bot.on(:callback_query) do |ctx|
|
|
328
|
-
ctx.reply("Button clicked!")
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
# โ
RIGHT
|
|
332
|
-
bot.on(:callback_query) do |ctx|
|
|
333
|
-
ctx.answer_callback_query # Tell Telegram we handled it
|
|
334
|
-
ctx.reply("Button clicked!")
|
|
335
|
-
end
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
Mistake 3: Not checking chat type
|
|
339
|
-
|
|
340
|
-
```ruby
|
|
341
|
-
# โ WRONG (might not work in channels)
|
|
342
|
-
ctx.reply("Hello!")
|
|
343
|
-
|
|
344
|
-
# โ
RIGHT
|
|
345
|
-
if ctx.chat.type != "channel"
|
|
346
|
-
ctx.reply("Hello!")
|
|
347
|
-
end
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
๐ฎ Interactive Learning Challenge
|
|
351
|
-
|
|
352
|
-
Build this in 10 minutes:
|
|
353
|
-
|
|
354
|
-
1. /hello - Replies with user's name
|
|
355
|
-
2. /dice - Rolls random number 1-6
|
|
356
|
-
3. /remember - Remembers what you say
|
|
357
|
-
4. /forget - Forgets everything
|
|
358
|
-
5. Buttons - Yes/No keyboard that works
|
|
359
|
-
|
|
360
|
-
```ruby
|
|
361
|
-
# Starter code - you finish it!
|
|
362
|
-
bot.command('hello') do |ctx|
|
|
363
|
-
# Your code here
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
bot.command('dice') do |ctx|
|
|
367
|
-
# Your code here (hint: rand(1..6))
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
bot.command('remember') do |ctx|
|
|
371
|
-
# Store in ctx.session[:memory]
|
|
372
|
-
end
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
๐ Cheat Sheet
|
|
376
|
-
|
|
377
|
-
Want to... Use... Example
|
|
378
|
-
- Send text ctx.reply() ctx.reply("Hi!")
|
|
379
|
-
- Send photo ctx.photo() ctx.photo("cat.jpg")
|
|
380
|
-
- Get user ID ctx.from.id id = ctx.from.id
|
|
381
|
-
- Check chat type ctx.chat.type if ctx.chat.type == "private"
|
|
382
|
-
- Remember data ctx.session[] ctx.session[:count] = 5
|
|
383
|
-
- Temp data ctx.state[] ctx.state[:asking] = true
|
|
384
|
-
- Button clicks ctx.data if ctx.data == "yes"
|
|
385
|
-
- Edit message ctx.edit_message_text() - -ctx.edit_message_text("Updated!")
|
|
386
|
-
|
|
387
|
-
๐ Next Steps Mastery Path
|
|
388
|
-
|
|
389
|
-
Week 1-2: Use everything in this guide
|
|
390
|
-
Week 3-4: Add keyboards and inline buttons
|
|
391
|
-
Week 5-6: Build multi-step scenes
|
|
392
|
-
Week 7-8: Add database persistence
|
|
393
|
-
Week 9-10: Deploy to cloud
|
|
394
|
-
|
|
395
|
-
---
|
|
396
|
-
|
|
397
|
-
Remember: ctx is your Swiss Army knife. The more you use it, the more natural it becomes. Start simple, build gradually, and soon you'll be building bots that feel magical! โจ
|
|
398
|
-
|
|
399
|
-
Your mission: Build one thing from this guide TODAY. Just one. Then build another tomorrow. Consistency beats complexity every time.
|
data/docs-src/getting-started.md
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# Getting Started with Telegem ๐
|
|
3
|
-
|
|
4
|
-
Build your first Telegram bot in 5 minutes with Ruby!
|
|
5
|
-
|
|
6
|
-
## ๐ Prerequisites
|
|
7
|
-
|
|
8
|
-
### 1. Install Ruby
|
|
9
|
-
```bash
|
|
10
|
-
# Check your Ruby version
|
|
11
|
-
ruby --version
|
|
12
|
-
# Should be 2.7 or higher (Ruby 3.0+ recommended)
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
2. Install Bundler (Optional but recommended)
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
gem install bundler
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
๐ฏ Quick Start - Your First Bot in 5 Minutes
|
|
22
|
-
|
|
23
|
-
Step 1: Get Your Bot Token
|
|
24
|
-
|
|
25
|
-
1. Open Telegram, search for @BotFather
|
|
26
|
-
2. Send /newbot and follow the prompts
|
|
27
|
-
3. Copy your token (looks like: 1234567890:ABCdefGHIjklMNOpqrsTUVwxyz)
|
|
28
|
-
|
|
29
|
-
<img src="Bot-registration_.PNG" width="600" alt="BotFather Conversation">
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Step 2: Create Your Bot
|
|
33
|
-
|
|
34
|
-
Option A: Using Bundler (Recommended)
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Create a new directory
|
|
38
|
-
mkdir my-telegram-bot
|
|
39
|
-
cd my-telegram-bot
|
|
40
|
-
|
|
41
|
-
# Create Gemfile
|
|
42
|
-
echo "source 'https://rubygems.org'
|
|
43
|
-
gem 'telegem'" > Gemfile
|
|
44
|
-
|
|
45
|
-
# Install gem
|
|
46
|
-
bundle install
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Option B: Direct Install
|
|
50
|
-
|
|
51
|
-
```bash
|
|
52
|
-
gem install telegem
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
Step 3: Write Your Bot Code
|
|
56
|
-
|
|
57
|
-
Create bot.rb:
|
|
58
|
-
|
|
59
|
-
```ruby
|
|
60
|
-
require 'telegem'
|
|
61
|
-
|
|
62
|
-
# Initialize with your token
|
|
63
|
-
bot = Telegem.new(ENV['BOT_TOKEN'])
|
|
64
|
-
|
|
65
|
-
# Handle /start command
|
|
66
|
-
bot.command('start') do |ctx|
|
|
67
|
-
ctx.reply("Hello #{ctx.from.first_name}! ๐")
|
|
68
|
-
ctx.reply("I'm your first Telegem bot!")
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Echo messages
|
|
72
|
-
bot.on(:message) do |ctx|
|
|
73
|
-
ctx.reply("You said: #{ctx.message.text}")
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Start the bot (polling mode for development)
|
|
77
|
-
bot.start_polling
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Step 4: Run Your Bot
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
# Set your token (on Linux/Mac)
|
|
84
|
-
export BOT_TOKEN="your_token_here"
|
|
85
|
-
|
|
86
|
-
# On Windows:
|
|
87
|
-
# set BOT_TOKEN=your_token_here
|
|
88
|
-
|
|
89
|
-
# Run the bot
|
|
90
|
-
ruby bot.rb
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Expected Output:
|
|
94
|
-
|
|
95
|
-
```
|
|
96
|
-
๐ค Starting Telegem bot (polling mode)...
|
|
97
|
-
โ
Bot is running!
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Step 5: Test Your Bot
|
|
101
|
-
|
|
102
|
-
1. Open Telegram, search for your bot (the username you gave @BotFather)
|
|
103
|
-
2. Send /start
|
|
104
|
-
3. You should see: "Hello [Your Name]! ๐"
|
|
105
|
-
|
|
106
|
-
๐ Congratulations! Your bot is alive!
|
|
107
|
-
|
|
108
|
-
๐ Next Steps
|
|
109
|
-
|
|
110
|
-
Choose Your Development Mode
|
|
111
|
-
|
|
112
|
-
Polling Mode (Development/Local)
|
|
113
|
-
|
|
114
|
-
```ruby
|
|
115
|
-
# Good for testing
|
|
116
|
-
bot.start_polling(
|
|
117
|
-
timeout: 30,
|
|
118
|
-
limit: 100
|
|
119
|
-
)
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Webhook Mode (Production)
|
|
123
|
-
|
|
124
|
-
```ruby
|
|
125
|
-
# One line - auto-detects cloud platform
|
|
126
|
-
bot.webhook.run
|
|
127
|
-
# Works with: Render, Railway, Heroku, Fly.io
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Add More Features
|
|
131
|
-
|
|
132
|
-
Keyboard Example:
|
|
133
|
-
|
|
134
|
-
```ruby
|
|
135
|
-
bot.command('menu') do |ctx|
|
|
136
|
-
keyboard = Telegem.keyboard do
|
|
137
|
-
row "Option 1", "Option 2"
|
|
138
|
-
row "Cancel"
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
ctx.reply("Choose an option:", reply_markup: keyboard)
|
|
142
|
-
end
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Inline Keyboard Example:
|
|
146
|
-
|
|
147
|
-
```ruby
|
|
148
|
-
bot.command('vote') do |ctx|
|
|
149
|
-
inline = Telegem.inline do
|
|
150
|
-
row button "๐ Like", callback_data: "like"
|
|
151
|
-
row button "๐ Dislike", callback_data: "dislike"
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
ctx.reply("Rate this:", reply_markup: inline)
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Handle button clicks
|
|
158
|
-
bot.on(:callback_query) do |ctx|
|
|
159
|
-
ctx.answer_callback_query(text: "Thanks for voting!")
|
|
160
|
-
end
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
๐ Project Structure
|
|
164
|
-
|
|
165
|
-
For larger projects, organize your code:
|
|
166
|
-
|
|
167
|
-
```
|
|
168
|
-
my-bot/
|
|
169
|
-
โโโ bot.rb # Main entry point
|
|
170
|
-
โโโ Gemfile
|
|
171
|
-
โโโ Gemfile.lock
|
|
172
|
-
โโโ config/
|
|
173
|
-
โ โโโ environment.rb # Load environment
|
|
174
|
-
โโโ handlers/
|
|
175
|
-
โ โโโ commands.rb # Command handlers
|
|
176
|
-
โ โโโ messages.rb # Message handlers
|
|
177
|
-
โ โโโ callbacks.rb # Callback handlers
|
|
178
|
-
โโโ .env # Environment variables
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
Example modular structure: See examples/modular-bot
|
|
182
|
-
|
|
183
|
-
๐ง Configuration
|
|
184
|
-
|
|
185
|
-
Environment Variables
|
|
186
|
-
|
|
187
|
-
Create .env file:
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
BOT_TOKEN=your_token_here
|
|
191
|
-
RACK_ENV=development
|
|
192
|
-
PORT=3000
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
Load with dotenv gem:
|
|
196
|
-
|
|
197
|
-
```ruby
|
|
198
|
-
# Gemfile
|
|
199
|
-
gem 'dotenv', groups: [:development, :test]
|
|
200
|
-
|
|
201
|
-
# In your bot.rb
|
|
202
|
-
require 'dotenv'
|
|
203
|
-
Dotenv.load
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
Bot Options
|
|
207
|
-
|
|
208
|
-
```ruby
|
|
209
|
-
bot = Telegem.new(ENV['BOT_TOKEN'],
|
|
210
|
-
logger: Logger.new('bot.log'), # Custom logger
|
|
211
|
-
timeout: 60, # API timeout
|
|
212
|
-
max_threads: 20, # Worker threads
|
|
213
|
-
session_store: custom_store # Custom session storage
|
|
214
|
-
)
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
๐ Troubleshooting
|
|
218
|
-
|
|
219
|
-
Common Issues
|
|
220
|
-
|
|
221
|
-
1. Bot not responding?
|
|
222
|
-
|
|
223
|
-
```bash
|
|
224
|
-
# Check if bot is running
|
|
225
|
-
ps aux | grep ruby
|
|
226
|
-
|
|
227
|
-
# Check logs
|
|
228
|
-
tail -f bot.log
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
2. Token invalid?
|
|
232
|
-
|
|
233
|
-
ยท Verify with @BotFather using /token
|
|
234
|
-
ยท Make sure token starts with numbers and has a colon
|
|
235
|
-
|
|
236
|
-
3. Webhook failing on cloud platforms?
|
|
237
|
-
|
|
238
|
-
ยท Set PORT environment variable
|
|
239
|
-
ยท Enable "Always On" on Render ($7/month)
|
|
240
|
-
ยท Check platform logs
|
|
241
|
-
|
|
242
|
-
4. Getting rate limited?
|
|
243
|
-
|
|
244
|
-
```ruby
|
|
245
|
-
bot.start_polling(
|
|
246
|
-
timeout: 30, # Increase timeout
|
|
247
|
-
limit: 10 # Reduce updates per request
|
|
248
|
-
)
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
๐ฎ Example Bots
|
|
252
|
-
|
|
253
|
-
See real working bots built with Telegem:
|
|
254
|
-
|
|
255
|
-
Beginner Examples
|
|
256
|
-
|
|
257
|
-
ยท Echo Bot - Simple message repeater
|
|
258
|
-
ยท Pizza Order Bot - Food ordering with scenes
|
|
259
|
-
ยท Survey Bot - Multi-question surveys
|
|
260
|
-
|
|
261
|
-
Intermediate Examples
|
|
262
|
-
|
|
263
|
-
ยท Crypto Price Bot - Real-time price updates
|
|
264
|
-
ยท File Converter Bot - Convert images/PDFs
|
|
265
|
-
ยท GitHub Notifier - GitHub webhook receiver
|
|
266
|
-
|
|
267
|
-
Advanced Examples
|
|
268
|
-
|
|
269
|
-
ยท E-commerce Store - Full shopping experience
|
|
270
|
-
ยท Multi-language Support Bot - Supports 5 languages
|
|
271
|
-
ยท AI Chat Bot - OpenAI integration
|
|
272
|
-
|
|
273
|
-
(Links will be added as community builds bots! Submit yours via PR!)
|
|
274
|
-
|
|
275
|
-
๐ Learning Path
|
|
276
|
-
|
|
277
|
-
1. Week 1: Build echo bot, menu bot
|
|
278
|
-
2. Week 2: Add database, user sessions
|
|
279
|
-
3. Week 3: Deploy to Render/Railway
|
|
280
|
-
4. Week 4: Integrate external APIs (weather, news, etc.)
|
|
281
|
-
|
|
282
|
-
๐ Need Help?
|
|
283
|
-
|
|
284
|
-
Quick Questions
|
|
285
|
-
|
|
286
|
-
1. Check the API Reference
|
|
287
|
-
2. Look at examples/
|
|
288
|
-
3. Search GitHub Issues
|
|
289
|
-
|
|
290
|
-
Community Support
|
|
291
|
-
|
|
292
|
-
ยท GitHub Discussions: Ask questions
|
|
293
|
-
ยท Stack Overflow: Use tag [telegem]
|
|
294
|
-
ยท Telegram Group: @telegem_ruby
|
|
295
|
-
|
|
296
|
-
๐ Ready for Production?
|
|
297
|
-
|
|
298
|
-
Deployment Checklist
|
|
299
|
-
|
|
300
|
-
ยท Use webhook mode (bot.webhook.run)
|
|
301
|
-
ยท Set up environment variables
|
|
302
|
-
ยท Add error monitoring (Sentry, etc.)
|
|
303
|
-
ยท Configure logging
|
|
304
|
-
ยท Set up backup for session data
|
|
305
|
-
|
|
306
|
-
One-Click Deploy
|
|
307
|
-
|
|
308
|
-
https://render.com/images/deploy-to-render-button.svg
|
|
309
|
-
https://railway.app/button.svg
|
|
310
|
-
|
|
311
|
-
๐ What's Next?
|
|
312
|
-
|
|
313
|
-
1. Master Scenes for multi-step conversations
|
|
314
|
-
2. Add Database for persistent storage
|
|
315
|
-
3. Integrate Payments for monetization
|
|
316
|
-
4. Build Admin Panel for bot management
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
Built something cool? Submit your bot to examples/ via Pull Request!
|
|
321
|
-
|
|
322
|
-
Need a feature? Open a GitHub Issue
|
|
323
|
-
|
|
324
|
-
Found a bug? Report it with reproduction steps
|
|
325
|
-
|
|
326
|
-
---
|
|
327
|
-
|
|
328
|
-
Happy building! ๐ Your Telegram bot journey starts here!
|