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
data/docs/QuickStart.md
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# π Quick Start: Your First Bot in 5 Minutes
|
|
3
|
-
|
|
4
|
-
Welcome! This guide will help you create your first Telegram bot with Telegem. No prior bot experience needed!
|
|
5
|
-
|
|
6
|
-
## π What You'll Need
|
|
7
|
-
|
|
8
|
-
1. **Ruby installed** (version 3.0 or newer)
|
|
9
|
-
2. **A Telegram account**
|
|
10
|
-
3. **A bot token** (we'll get this next)
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## π Step 1: Get Your Bot Token
|
|
15
|
-
|
|
16
|
-
1. Open Telegram and search for **@BotFather**
|
|
17
|
-
2. Start a chat and send: `/newbot`
|
|
18
|
-
3. Choose a name for your bot (e.g., `My Test Bot`)
|
|
19
|
-
4. Choose a username ending in `bot` (e.g., `my_test_123_bot`)
|
|
20
|
-
5. **Copy the token** that looks like this:
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ-123456789
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
β οΈ **Keep this token secret!** It's your bot's password.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## π¦ Step 2: Install Telegem
|
|
31
|
-
|
|
32
|
-
Open your terminal and run:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
gem install telegem
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
You should see something like:
|
|
39
|
-
|
|
40
|
-
```
|
|
41
|
-
Successfully installed telegem-0.1.0
|
|
42
|
-
1 gem installed
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
π€ Step 3: Create Your First Bot
|
|
48
|
-
|
|
49
|
-
Create a new file called my_first_bot.rb:
|
|
50
|
-
|
|
51
|
-
```ruby
|
|
52
|
-
# my_first_bot.rb
|
|
53
|
-
require 'telegem'
|
|
54
|
-
|
|
55
|
-
# 1. Paste your token here (replace the example)
|
|
56
|
-
BOT_TOKEN = "1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ"
|
|
57
|
-
|
|
58
|
-
# 2. Create your bot
|
|
59
|
-
bot = Telegem.new(BOT_TOKEN)
|
|
60
|
-
|
|
61
|
-
# 3. Add your first command
|
|
62
|
-
bot.command('start') do |ctx|
|
|
63
|
-
ctx.reply "Hello! I'm your new bot. π"
|
|
64
|
-
ctx.reply "Try sending me /help"
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# 4. Add a help command
|
|
68
|
-
bot.command('help') do |ctx|
|
|
69
|
-
help_text = <<~TEXT
|
|
70
|
-
π€ **My First Bot Commands:**
|
|
71
|
-
|
|
72
|
-
/start - Start the bot
|
|
73
|
-
/help - Show this message
|
|
74
|
-
/echo [text] - Repeat your text
|
|
75
|
-
|
|
76
|
-
Just send me any message and I'll reply!
|
|
77
|
-
TEXT
|
|
78
|
-
|
|
79
|
-
ctx.reply help_text
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# 5. Add an echo command
|
|
83
|
-
bot.command('echo') do |ctx|
|
|
84
|
-
if ctx.message.text == "/echo"
|
|
85
|
-
ctx.reply "Please add some text: /echo hello world"
|
|
86
|
-
else
|
|
87
|
-
# Remove "/echo " from the beginning
|
|
88
|
-
text = ctx.message.text.sub('/echo ', '')
|
|
89
|
-
ctx.reply "You said: #{text}"
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# 6. Reply to ANY message
|
|
94
|
-
bot.on(:message) do |ctx|
|
|
95
|
-
# Don't reply to commands (they're handled above)
|
|
96
|
-
next if ctx.message.command?
|
|
97
|
-
|
|
98
|
-
ctx.reply "I got your message: #{ctx.message.text}"
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# 7. Start the bot
|
|
102
|
-
puts "π€ Bot starting... (Press Ctrl+C to stop)"
|
|
103
|
-
bot.start_polling
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
βΆοΈ Step 4: Run Your Bot
|
|
109
|
-
|
|
110
|
-
In your terminal, run:
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
ruby my_first_bot.rb
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
You should see:
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
π€ Bot starting... (Press Ctrl+C to stop)
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
Congratulations! Your bot is now running! π
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
π¬ Step 5: Test Your Bot
|
|
127
|
-
|
|
128
|
-
1. Open Telegram and search for your bot's username (e.g., @my_test_123_bot)
|
|
129
|
-
2. Click "Start"
|
|
130
|
-
3. Try these commands:
|
|
131
|
-
Β· /start - Should say hello
|
|
132
|
-
Β· /help - Should show commands
|
|
133
|
-
Β· /echo hello - Should repeat "hello"
|
|
134
|
-
Β· Send any normal message - Should echo it back
|
|
135
|
-
|
|
136
|
-
It should work like this:
|
|
137
|
-
|
|
138
|
-
```
|
|
139
|
-
You: /start
|
|
140
|
-
Bot: Hello! I'm your new bot. π
|
|
141
|
-
Bot: Try sending me /help
|
|
142
|
-
|
|
143
|
-
You: Hello bot!
|
|
144
|
-
Bot: I got your message: Hello bot!
|
|
145
|
-
|
|
146
|
-
You: /echo testing
|
|
147
|
-
Bot: You said: testing
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
π¨ Step 6: Add a Simple Keyboard
|
|
153
|
-
|
|
154
|
-
Let's make it more interactive! Update your bot with this:
|
|
155
|
-
|
|
156
|
-
```ruby
|
|
157
|
-
# Add this new command
|
|
158
|
-
bot.command('menu') do |ctx|
|
|
159
|
-
# Create a simple keyboard
|
|
160
|
-
keyboard = [
|
|
161
|
-
["Option 1", "Option 2"],
|
|
162
|
-
["Option 3", "Cancel"]
|
|
163
|
-
]
|
|
164
|
-
|
|
165
|
-
ctx.reply "Choose an option:", reply_markup: { keyboard: keyboard }
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
# Handle the keyboard button presses
|
|
169
|
-
bot.on(:message) do |ctx|
|
|
170
|
-
next if ctx.message.command?
|
|
171
|
-
|
|
172
|
-
text = ctx.message.text
|
|
173
|
-
|
|
174
|
-
case text
|
|
175
|
-
when "Option 1"
|
|
176
|
-
ctx.reply "You chose Option 1! β
"
|
|
177
|
-
when "Option 2"
|
|
178
|
-
ctx.reply "Option 2 selected! π"
|
|
179
|
-
when "Option 3"
|
|
180
|
-
ctx.reply "Option 3 picked! π―"
|
|
181
|
-
when "Cancel"
|
|
182
|
-
ctx.reply "Cancelled! β"
|
|
183
|
-
else
|
|
184
|
-
ctx.reply "I got: #{text}"
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
Restart your bot and try /menu to see the keyboard!
|
|
190
|
-
|
|
191
|
-
---
|
|
192
|
-
|
|
193
|
-
π οΈ Step 7: Common Fixes
|
|
194
|
-
|
|
195
|
-
"Token is invalid" error?
|
|
196
|
-
|
|
197
|
-
Β· Make sure you copied the entire token
|
|
198
|
-
Β· Check there are no spaces before/after
|
|
199
|
-
Β· Try creating a new bot with @BotFather
|
|
200
|
-
|
|
201
|
-
"gem not found" error?
|
|
202
|
-
|
|
203
|
-
Β· Run gem install telegem again
|
|
204
|
-
Β· Check Ruby version: ruby -v (should be 3.0+)
|
|
205
|
-
|
|
206
|
-
Bot not responding?
|
|
207
|
-
|
|
208
|
-
Β· Make sure your bot is running (ruby my_first_bot.rb)
|
|
209
|
-
Β· Check you've started the bot in Telegram (send /start)
|
|
210
|
-
Β· Wait a few seconds - sometimes there's a small delay
|
|
211
|
-
|
|
212
|
-
Want to stop the bot?
|
|
213
|
-
|
|
214
|
-
Press Ctrl+C in your terminal.
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
π Next Steps
|
|
219
|
-
|
|
220
|
-
Your bot is working! Now try:
|
|
221
|
-
|
|
222
|
-
1. Change the replies - Make the bot say different things
|
|
223
|
-
2. Add more commands - Try /time to send current time
|
|
224
|
-
3. Send a photo - Add this to your bot:
|
|
225
|
-
```ruby
|
|
226
|
-
bot.command('photo') do |ctx|
|
|
227
|
-
ctx.reply "Here's a cat! π±"
|
|
228
|
-
# Send a cat photo from the internet
|
|
229
|
-
ctx.photo("https://placekitten.com/400/400")
|
|
230
|
-
end
|
|
231
|
-
```
|
|
232
|
-
4. Check the examples - Look in the /examples folder for more ideas
|
|
233
|
-
5. Read the API Reference - When you're ready for more features, check api.md
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
π‘ Tips for Beginners
|
|
238
|
-
|
|
239
|
-
Β· Save your token safely - You'll need it every time
|
|
240
|
-
Β· Restart after changes - Stop (Ctrl+C) and restart your bot when you change the code
|
|
241
|
-
Β· Start simple - Get one thing working before adding more
|
|
242
|
-
Β· Use puts for debugging - Add puts "Got here!" to see what's happening
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
π Need Help?
|
|
247
|
-
|
|
248
|
-
1. Check your code against the examples above
|
|
249
|
-
2. Read error messages - They often tell you what's wrong
|
|
250
|
-
3. Ask for help - Open an issue on GitLab
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
π You did it! You've built your first Telegram bot. What will you create next?
|
|
255
|
-
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
---
|
data/docs/Understanding_Scene.md
DELETED
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
π§ Telegem Scenes: The Complete Guide (Without the Confusion)
|
|
2
|
-
|
|
3
|
-
Scenes are conversation flows in Telegem. They handle back-and-forth interactions like forms, surveys, or onboarding. Let's remove all confusion.
|
|
4
|
-
|
|
5
|
-
π The Two-Step Dance: Define vs. Start
|
|
6
|
-
|
|
7
|
-
Scenes work in two distinct phases:
|
|
8
|
-
|
|
9
|
-
```ruby
|
|
10
|
-
# PHASE 1: DEFINE (Write the script)
|
|
11
|
-
bot.scene :registration do
|
|
12
|
-
step :ask_name { |ctx| ctx.reply "What's your name?" }
|
|
13
|
-
step :ask_email { |ctx| ctx.reply "What's your email?" }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# PHASE 2: START (Run the script)
|
|
17
|
-
bot.command('register') do |ctx|
|
|
18
|
-
ctx.enter_scene(:registration) # This actually begins the scene
|
|
19
|
-
end
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
π― The Analogy That Makes Sense
|
|
23
|
-
|
|
24
|
-
Β· bot.scene = Writing a movie script
|
|
25
|
-
Β· ctx.enter_scene = Yelling "Action!" on set
|
|
26
|
-
Β· The scene steps = What the actors actually do
|
|
27
|
-
|
|
28
|
-
π§ The Complete Working Template
|
|
29
|
-
|
|
30
|
-
```ruby
|
|
31
|
-
require 'telegem'
|
|
32
|
-
|
|
33
|
-
bot = Telegem.new('YOUR_BOT_TOKEN')
|
|
34
|
-
|
|
35
|
-
# =============== DEFINE THE SCENE ===============
|
|
36
|
-
bot.scene :feedback do
|
|
37
|
-
# Optional: Runs when scene starts
|
|
38
|
-
on_enter do |ctx|
|
|
39
|
-
ctx.session[:feedback] = { user_id: ctx.from.id }
|
|
40
|
-
ctx.reply "π Let's collect your feedback!"
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Step 1: Ask for rating
|
|
44
|
-
step :ask_rating do |ctx|
|
|
45
|
-
keyboard = Telegem::Markup.inline do
|
|
46
|
-
row callback("βοΈ 1", "rating_1"), callback("βοΈ 2", "rating_2")
|
|
47
|
-
row callback("βοΈ 3", "rating_3"), callback("βοΈ 4", "rating_4"), callback("βοΈ 5", "rating_5")
|
|
48
|
-
end
|
|
49
|
-
ctx.reply "How would you rate us? (1-5 stars)", reply_markup: keyboard
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Step 2: Handle rating choice
|
|
53
|
-
step :handle_rating do |ctx|
|
|
54
|
-
if ctx.data&.start_with?('rating_')
|
|
55
|
-
rating = ctx.data.split('_').last.to_i
|
|
56
|
-
ctx.session[:feedback][:rating] = rating
|
|
57
|
-
ctx.reply "Thanks! Now please share your comments:"
|
|
58
|
-
else
|
|
59
|
-
ctx.reply "Please use the buttons above β¬οΈ"
|
|
60
|
-
return # Stay on this step
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Step 3: Collect comments
|
|
65
|
-
step :collect_comments do |ctx|
|
|
66
|
-
if ctx.message.text
|
|
67
|
-
ctx.session[:feedback][:comments] = ctx.message.text
|
|
68
|
-
|
|
69
|
-
# Show summary
|
|
70
|
-
summary = <<~SUMMARY
|
|
71
|
-
π **Feedback Summary:**
|
|
72
|
-
|
|
73
|
-
Rating: #{ctx.session[:feedback][:rating]} stars
|
|
74
|
-
Comments: #{ctx.session[:feedback][:comments]}
|
|
75
|
-
|
|
76
|
-
Submit? (yes/no)
|
|
77
|
-
SUMMARY
|
|
78
|
-
|
|
79
|
-
ctx.reply summary, parse_mode: 'Markdown'
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Step 4: Final confirmation
|
|
84
|
-
step :confirm do |ctx|
|
|
85
|
-
if ctx.message.text&.downcase == 'yes'
|
|
86
|
-
save_feedback(ctx.session[:feedback])
|
|
87
|
-
ctx.reply "β
Feedback submitted! Thank you."
|
|
88
|
-
else
|
|
89
|
-
ctx.reply "β Feedback cancelled."
|
|
90
|
-
end
|
|
91
|
-
ctx.leave_scene
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# Optional: Runs when scene ends (success or cancel)
|
|
95
|
-
on_leave do |ctx|
|
|
96
|
-
ctx.session.delete(:feedback)
|
|
97
|
-
ctx.reply "Back to main menu!"
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# =============== START THE SCENE ===============
|
|
102
|
-
bot.command('feedback') do |ctx|
|
|
103
|
-
ctx.enter_scene(:feedback) # THIS actually starts it
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Start the bot
|
|
107
|
-
bot.start_polling
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
π¦ 4 Production-Ready Scene Templates
|
|
111
|
-
|
|
112
|
-
Template 1: Simple Form (Beginner Friendly)
|
|
113
|
-
|
|
114
|
-
Perfect for basic data collection.
|
|
115
|
-
|
|
116
|
-
```ruby
|
|
117
|
-
bot.scene :quick_survey do
|
|
118
|
-
on_enter { |ctx| ctx.reply "Quick 3-question survey:" }
|
|
119
|
-
|
|
120
|
-
step :q1 do |ctx|
|
|
121
|
-
ctx.reply "1. What's your favorite language? (Ruby/JS/Python)"
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
step :q2 do |ctx|
|
|
125
|
-
ctx.session[:lang] = ctx.message.text
|
|
126
|
-
ctx.reply "2. How many years experience?"
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
step :q3 do |ctx|
|
|
130
|
-
ctx.session[:exp] = ctx.message.text
|
|
131
|
-
ctx.reply "3. What's your biggest challenge?"
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
step :finish do |ctx|
|
|
135
|
-
ctx.session[:challenge] = ctx.message.text
|
|
136
|
-
save_survey(ctx.session)
|
|
137
|
-
ctx.reply "β
Survey complete! Thanks for sharing."
|
|
138
|
-
ctx.leave_scene
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# Usage: /survey
|
|
143
|
-
bot.command('survey') { |ctx| ctx.enter_scene(:quick_survey) }
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
Template 2: Menu Navigator (With Branching)
|
|
147
|
-
|
|
148
|
-
For complex flows with different paths.
|
|
149
|
-
|
|
150
|
-
```ruby
|
|
151
|
-
bot.scene :support_ticket do
|
|
152
|
-
step :ask_type do |ctx|
|
|
153
|
-
keyboard = Telegem::Markup.keyboard do
|
|
154
|
-
row "π Bug Report", "β¨ Feature Request"
|
|
155
|
-
row "β Question", "π§ Technical Issue"
|
|
156
|
-
end
|
|
157
|
-
ctx.reply "What type of support do you need?", reply_markup: keyboard
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
step :collect_details do |ctx|
|
|
161
|
-
type = ctx.message.text
|
|
162
|
-
ctx.session[:ticket_type] = type
|
|
163
|
-
|
|
164
|
-
case type
|
|
165
|
-
when "π Bug Report"
|
|
166
|
-
ctx.reply "Describe the bug (steps to reproduce):"
|
|
167
|
-
ctx.session[:next_action] = :save_bug
|
|
168
|
-
when "β¨ Feature Request"
|
|
169
|
-
ctx.reply "Describe the feature you'd like:"
|
|
170
|
-
ctx.session[:next_action] = :save_feature
|
|
171
|
-
else
|
|
172
|
-
ctx.reply "Describe your issue:"
|
|
173
|
-
ctx.session[:next_action] = :save_general
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
step :process_ticket do |ctx|
|
|
178
|
-
description = ctx.message.text
|
|
179
|
-
ticket_id = "TICKET-#{SecureRandom.hex(4).upcase}"
|
|
180
|
-
|
|
181
|
-
case ctx.session[:next_action]
|
|
182
|
-
when :save_bug
|
|
183
|
-
save_to_database(type: 'bug', desc: description, id: ticket_id)
|
|
184
|
-
ctx.reply "π Bug logged as #{ticket_id}"
|
|
185
|
-
when :save_feature
|
|
186
|
-
save_to_database(type: 'feature', desc: description, id: ticket_id)
|
|
187
|
-
ctx.reply "β¨ Feature requested as #{ticket_id}"
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
ctx.leave_scene
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
on_leave do |ctx|
|
|
194
|
-
ctx.reply "Support will contact you soon. Use /status to check ticket."
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
# Usage: /support
|
|
199
|
-
bot.command('support') { |ctx| ctx.enter_scene(:support_ticket) }
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
Template 3: Async Data Fetching (Advanced)
|
|
203
|
-
|
|
204
|
-
For scenes that need to fetch external data.
|
|
205
|
-
|
|
206
|
-
```ruby
|
|
207
|
-
bot.scene :github_analyzer do
|
|
208
|
-
step :ask_repo do |ctx|
|
|
209
|
-
ctx.reply "Enter a GitHub repo URL (e.g., https://github.com/user/repo):"
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
step :fetch_data do |ctx|
|
|
213
|
-
url = ctx.message.text
|
|
214
|
-
|
|
215
|
-
# Show loading
|
|
216
|
-
ctx.reply "β³ Fetching repo data..."
|
|
217
|
-
|
|
218
|
-
# Async HTTP request
|
|
219
|
-
Async do
|
|
220
|
-
begin
|
|
221
|
-
# Fetch from GitHub API using httpx
|
|
222
|
-
data = await fetch_github_data(url)
|
|
223
|
-
|
|
224
|
-
# Show results
|
|
225
|
-
info = <<~INFO
|
|
226
|
-
π **Repo Analysis:**
|
|
227
|
-
|
|
228
|
-
Name: #{data[:name]}
|
|
229
|
-
Stars: #{data[:stars]}
|
|
230
|
-
Language: #{data[:language]}
|
|
231
|
-
Description: #{data[:description]}
|
|
232
|
-
|
|
233
|
-
Last updated: #{data[:updated_at]}
|
|
234
|
-
INFO
|
|
235
|
-
|
|
236
|
-
ctx.reply info, parse_mode: 'Markdown'
|
|
237
|
-
|
|
238
|
-
rescue => e
|
|
239
|
-
ctx.reply "β Error: #{e.message}"
|
|
240
|
-
ensure
|
|
241
|
-
ctx.leave_scene
|
|
242
|
-
end
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
# Usage: /analyze
|
|
248
|
-
bot.command('analyze') { |ctx| ctx.enter_scene(:github_analyzer) }
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Template 4: Multi-Step With Validation (Production Ready)
|
|
252
|
-
|
|
253
|
-
Includes proper error handling and validation.
|
|
254
|
-
|
|
255
|
-
```ruby
|
|
256
|
-
bot.scene :user_registration, timeout: 300 do # 5 minute timeout
|
|
257
|
-
on_enter do |ctx|
|
|
258
|
-
ctx.session[:registration] = {
|
|
259
|
-
started_at: Time.now,
|
|
260
|
-
attempts: 0,
|
|
261
|
-
data: {}
|
|
262
|
-
}
|
|
263
|
-
ctx.reply "π€ Registration Process\n\nLet's get started!"
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
step :ask_email do |ctx|
|
|
267
|
-
ctx.reply "Enter your email address:"
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
step :validate_email do |ctx|
|
|
271
|
-
email = ctx.message.text.strip
|
|
272
|
-
|
|
273
|
-
unless email.include?('@') && email.include?('.')
|
|
274
|
-
ctx.session[:registration][:attempts] += 1
|
|
275
|
-
|
|
276
|
-
if ctx.session[:registration][:attempts] >= 3
|
|
277
|
-
ctx.reply "β Too many attempts. Registration cancelled."
|
|
278
|
-
ctx.leave_scene
|
|
279
|
-
return
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
ctx.reply "β Invalid email format. Please try again:"
|
|
283
|
-
return # Stay on this step
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
# Email is valid
|
|
287
|
-
ctx.session[:registration][:data][:email] = email
|
|
288
|
-
ctx.session[:registration][:attempts] = 0
|
|
289
|
-
ctx.reply "β
Email accepted!"
|
|
290
|
-
ctx.reply "Enter your full name:"
|
|
291
|
-
end
|
|
292
|
-
|
|
293
|
-
step :ask_password do |ctx|
|
|
294
|
-
ctx.session[:registration][:data][:name] = ctx.message.text
|
|
295
|
-
ctx.reply "Create a password (min 8 characters):"
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
step :confirm_registration do |ctx|
|
|
299
|
-
password = ctx.message.text
|
|
300
|
-
|
|
301
|
-
if password.length < 8
|
|
302
|
-
ctx.reply "β Password too short. Min 8 characters:"
|
|
303
|
-
return
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
ctx.session[:registration][:data][:password] = password
|
|
307
|
-
|
|
308
|
-
# Show summary
|
|
309
|
-
summary = <<~SUMMARY
|
|
310
|
-
π **Registration Summary:**
|
|
311
|
-
|
|
312
|
-
Email: #{ctx.session[:registration][:data][:email]}
|
|
313
|
-
Name: #{ctx.session[:registration][:data][:name]}
|
|
314
|
-
|
|
315
|
-
Confirm registration? (yes/no)
|
|
316
|
-
SUMMARY
|
|
317
|
-
|
|
318
|
-
ctx.reply summary, parse_mode: 'Markdown'
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
step :finalize do |ctx|
|
|
322
|
-
if ctx.message.text&.downcase == 'yes'
|
|
323
|
-
# Save to database
|
|
324
|
-
user_id = create_user(ctx.session[:registration][:data])
|
|
325
|
-
ctx.reply "β
Registration complete!\nYour ID: #{user_id}"
|
|
326
|
-
else
|
|
327
|
-
ctx.reply "β Registration cancelled."
|
|
328
|
-
end
|
|
329
|
-
ctx.leave_scene
|
|
330
|
-
end
|
|
331
|
-
|
|
332
|
-
on_timeout do |ctx|
|
|
333
|
-
ctx.reply "β° Registration timed out. Please start over with /register."
|
|
334
|
-
ctx.session.delete(:registration)
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
on_leave do |ctx|
|
|
338
|
-
# Cleanup
|
|
339
|
-
ctx.session.delete(:registration)
|
|
340
|
-
end
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
# Usage: /register
|
|
344
|
-
bot.command('register') { |ctx| ctx.enter_scene(:user_registration) }
|
|
345
|
-
```
|
|
346
|
-
|
|
347
|
-
π Common Patterns Cheat Sheet
|
|
348
|
-
|
|
349
|
-
Pattern 1: Basic Form Flow
|
|
350
|
-
|
|
351
|
-
```ruby
|
|
352
|
-
bot.scene :simple_form
|
|
353
|
-
bot.command('start_form') { |ctx| ctx.enter_scene(:simple_form) }
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
Pattern 2: Inline Button Navigation
|
|
357
|
-
|
|
358
|
-
```ruby
|
|
359
|
-
bot.scene :menu_driven
|
|
360
|
-
# Uses callback buttons for choices
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
Pattern 3: Async Operations
|
|
364
|
-
|
|
365
|
-
```ruby
|
|
366
|
-
bot.scene :async_task
|
|
367
|
-
# Uses Async { } for HTTP/DB operations
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
Pattern 4: Validated Input
|
|
371
|
-
|
|
372
|
-
```ruby
|
|
373
|
-
bot.scene :validated_input
|
|
374
|
-
# Uses return to stay on step when validation fails
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
π§ Debugging Scenes: Quick Fixes
|
|
378
|
-
|
|
379
|
-
β "Scene doesn't start!"
|
|
380
|
-
|
|
381
|
-
Check: Did you call ctx.enter_scene?
|
|
382
|
-
|
|
383
|
-
```ruby
|
|
384
|
-
bot.command('start') do |ctx|
|
|
385
|
-
ctx.enter_scene(:your_scene) # β MUST BE PRESENT
|
|
386
|
-
end
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
β "Steps skip unexpectedly!"
|
|
390
|
-
|
|
391
|
-
Cause: Missing return on validation failure
|
|
392
|
-
Fix:
|
|
393
|
-
|
|
394
|
-
```ruby
|
|
395
|
-
step :collect_age do |ctx|
|
|
396
|
-
age = ctx.message.text.to_i
|
|
397
|
-
if age < 18
|
|
398
|
-
ctx.reply "Must be 18+. Try again:"
|
|
399
|
-
return # β THIS keeps you on the same step
|
|
400
|
-
end
|
|
401
|
-
# Continues only if age >= 18
|
|
402
|
-
end
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
β "Data lost between steps!"
|
|
406
|
-
|
|
407
|
-
Solution: Use ctx.session
|
|
408
|
-
|
|
409
|
-
```ruby
|
|
410
|
-
step :one do |ctx|
|
|
411
|
-
ctx.session[:temp] = "saved data" # β Save
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
step :two do |ctx|
|
|
415
|
-
data = ctx.session[:temp] # β Retrieve
|
|
416
|
-
end
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
π Remember This Mental Model
|
|
420
|
-
|
|
421
|
-
1. Define once (bot.scene) - Teach the bot a conversation pattern
|
|
422
|
-
2. Start many times (ctx.enter_scene) - Begin that conversation with users
|
|
423
|
-
3. Steps auto-advance - After user responds, Telegem moves to next step
|
|
424
|
-
4. Use ctx.session - Store data between steps
|
|
425
|
-
5. Clean up in on_leave - Remove session data when done
|
|
426
|
-
|
|
427
|
-
π― Your Homework (Test Understanding)
|
|
428
|
-
|
|
429
|
-
1. Create a pizza ordering scene with size and toppings
|
|
430
|
-
2. Add validation (size must be S/M/L, max 3 toppings)
|
|
431
|
-
3. Add a timeout of 10 minutes
|
|
432
|
-
4. Test it with /order_pizza
|
|
433
|
-
|
|
434
|
-
You now have everything you need to build robust scenes. The key is practiceβstart simple, then add complexity one piece at a time.
|