telegem 0.2.0 โ 1.0.0
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/.replit +13 -0
- data/Contributing.md +553 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +11 -0
- data/LICENSE +21 -0
- data/Readme.md +353 -0
- data/Test-Projects/.gitkeep +0 -0
- data/Test-Projects/bot_test1.rb +75 -0
- data/Test-Projects/pizza_test_bot_guide.md +163 -0
- data/docs/.gitkeep +0 -0
- data/docs/Api.md +419 -0
- data/docs/Cookbook.md +407 -0
- data/docs/How_to_use.md +571 -0
- data/docs/QuickStart.md +258 -0
- data/docs/Usage.md +717 -0
- data/lib/api/client.rb +134 -154
- data/lib/core/bot.rb +102 -96
- data/lib/core/composer.rb +36 -18
- data/lib/core/context.rb +180 -177
- data/lib/core/scene.rb +81 -71
- data/lib/session/memory_store.rb +1 -1
- data/lib/session/middleware.rb +20 -36
- data/lib/telegem.rb +57 -54
- data/lib/webhook/.gitkeep +0 -0
- data/lib/webhook/server.rb +193 -0
- metadata +38 -35
- data/telegem.gemspec +0 -43
- data/webhook/server.rb +0 -86
data/Readme.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
Telegem ๐คโก
|
|
2
|
+
|
|
3
|
+
Modern, blazing-fast async Telegram Bot API for Ruby - Inspired by Telegraf, built for performance.
|
|
4
|
+
|
|
5
|
+
    
|
|
6
|
+
|
|
7
|
+
Blazing-fast, modern Telegram Bot framework for Ruby. Inspired by Telegraf.js, built for performance with true async/await patterns.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
โจ Features
|
|
12
|
+
|
|
13
|
+
ยท โก True Async I/O - Built on async gem, not blocking threads
|
|
14
|
+
ยท ๐ฏ Telegraf-style DSL - Familiar API for JavaScript developers
|
|
15
|
+
ยท ๐ Middleware System - Compose behavior like Express.js
|
|
16
|
+
ยท ๐ง Scene System - Multi-step conversations (wizards/forms)
|
|
17
|
+
ยท ๐พ Session Management - Redis, memory, or custom stores
|
|
18
|
+
ยท โจ๏ธ Keyboard DSL - Clean markup builders with fluent API
|
|
19
|
+
ยท ๐ Webhook Server - Production-ready async HTTP server
|
|
20
|
+
ยท ๐๏ธ Type-Safe Objects - Ruby classes for all Telegram types
|
|
21
|
+
ยท ๐ฆ Minimal Dependencies - Just async gems + mime-types
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
๐ Quick Start
|
|
26
|
+
|
|
27
|
+
Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
gem install telegem
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or add to your Gemfile:
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
gem 'telegem'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Your First Bot (in 60 seconds)
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
require 'telegem'
|
|
43
|
+
|
|
44
|
+
# 1. Get token from @BotFather on Telegram
|
|
45
|
+
bot = Telegem.new('YOUR_BOT_TOKEN')
|
|
46
|
+
|
|
47
|
+
# 2. Add commands
|
|
48
|
+
bot.command('start') do |ctx|
|
|
49
|
+
ctx.reply "Hello #{ctx.from.first_name}! ๐"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
bot.command('help') do |ctx|
|
|
53
|
+
ctx.reply "I'm your friendly Telegem bot!"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# 3. Start listening
|
|
57
|
+
puts "๐ค Bot starting..."
|
|
58
|
+
bot.start_polling
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Interactive Example
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
# Pizza ordering bot example
|
|
65
|
+
bot.command('order') do |ctx|
|
|
66
|
+
keyboard = Telegem::Markup.keyboard do
|
|
67
|
+
row "๐ Margherita", "๐ Pepperoni"
|
|
68
|
+
row "๐ฅค Drinks", "๐ฐ Dessert"
|
|
69
|
+
row "๐ Support", "โ Cancel"
|
|
70
|
+
end.resize.one_time
|
|
71
|
+
|
|
72
|
+
ctx.reply "What would you like?", reply_markup: keyboard
|
|
73
|
+
end
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
๐ธ See It in Action
|
|
79
|
+
|
|
80
|
+
https://your-image-link-here.com/telegem-demo.gif <!-- Replace with your demo GIF -->
|
|
81
|
+
|
|
82
|
+
Example bot with interactive keyboard and scene-based ordering flow
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
๐ฏ Why Telegem?
|
|
87
|
+
|
|
88
|
+
vs. Other Ruby Telegram Libraries
|
|
89
|
+
|
|
90
|
+
Feature Telegem telegram-bot-ruby Others
|
|
91
|
+
Async Architecture โ
True async/await โ Thread-based โ Blocking
|
|
92
|
+
Middleware System โ
Express.js-style โ Limited โ None
|
|
93
|
+
Scene Management โ
Built-in โ Manual โ None
|
|
94
|
+
Session Stores โ
Multiple โ Basic โ None
|
|
95
|
+
Modern DSL โ
Clean & fluent โ Verbose โ ๏ธ Varies
|
|
96
|
+
Performance โ
Non-blocking โ ๏ธ OK โ Poor
|
|
97
|
+
|
|
98
|
+
Perfect For:
|
|
99
|
+
|
|
100
|
+
- High-traffic bots needing async performance
|
|
101
|
+
- Complex conversations with multi-step flows
|
|
102
|
+
- Production deployments with webhooks & scaling
|
|
103
|
+
- Developers familiar with Telegraf.js/Express
|
|
104
|
+
- Modern Ruby (3.0+) applications
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
๐ Documentation
|
|
109
|
+
|
|
110
|
+
Getting Started
|
|
111
|
+
|
|
112
|
+
1. How to Use - Beginner-friendly tutorial
|
|
113
|
+
2. Usage Guide - Advanced patterns & best practices
|
|
114
|
+
3. Cookbook - Copy-paste recipes for common tasks
|
|
115
|
+
4. API Reference - Complete method documentation
|
|
116
|
+
|
|
117
|
+
Quick Links
|
|
118
|
+
|
|
119
|
+
ยท [Creating Your First Bot](https://gitlab.com/ruby-telegem/telegem/-/blob/main/docs/QuickStart.md)
|
|
120
|
+
ยท [Understanding Context (ctx)](https://gitlab.com/ruby-telegem/telegem/-/blob/main/docs/How_to_use.md)
|
|
121
|
+
ยท [Building Scenes](https://gitlab.com/ruby-telegem/telegem/-/blob/main/docs/Usage.md)
|
|
122
|
+
ยท Middleware Patterns
|
|
123
|
+
ยท Deployment Guide
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
๐งฉ Advanced Features
|
|
128
|
+
|
|
129
|
+
Scene System (Multi-step Conversations)
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
bot.scene :registration do
|
|
133
|
+
step :ask_name do |ctx|
|
|
134
|
+
ctx.reply "What's your name?"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
step :save_name do |ctx|
|
|
138
|
+
ctx.session[:name] = ctx.message.text
|
|
139
|
+
ctx.reply "Hi #{ctx.session[:name]}! What's your email?"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
step :complete do |ctx|
|
|
143
|
+
ctx.session[:email] = ctx.message.text
|
|
144
|
+
ctx.reply "Registration complete! โ
"
|
|
145
|
+
ctx.leave_scene
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Middleware Pipeline
|
|
151
|
+
|
|
152
|
+
```ruby
|
|
153
|
+
# Add cross-cutting concerns
|
|
154
|
+
bot.use AuthenticationMiddleware.new
|
|
155
|
+
bot.use RateLimiter.new(limit: 10)
|
|
156
|
+
bot.use LoggingMiddleware.new
|
|
157
|
+
|
|
158
|
+
# Custom middleware
|
|
159
|
+
bot.use do |ctx, next_middleware|
|
|
160
|
+
puts "Processing message from #{ctx.from.username}"
|
|
161
|
+
next_middleware.call(ctx)
|
|
162
|
+
end
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Multiple Session Stores
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
# Memory (development)
|
|
169
|
+
Telegem::Session::MemoryStore.new
|
|
170
|
+
|
|
171
|
+
# Redis (production)
|
|
172
|
+
require 'redis'
|
|
173
|
+
redis = Redis.new(url: ENV['REDIS_URL'])
|
|
174
|
+
Telegem::Session::RedisStore.new(redis)
|
|
175
|
+
|
|
176
|
+
# Custom (database, etc.)
|
|
177
|
+
class DatabaseStore
|
|
178
|
+
def get(user_id); end
|
|
179
|
+
def set(user_id, data); end
|
|
180
|
+
end
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
๐ Production Deployment
|
|
186
|
+
|
|
187
|
+
Webhook Mode (Recommended)
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
# Production setup
|
|
191
|
+
server = bot.webhook_server(
|
|
192
|
+
port: ENV['PORT'] || 3000,
|
|
193
|
+
endpoint: Async::HTTP::Endpoint.parse("https://#{ENV['DOMAIN']}")
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Set webhook automatically
|
|
197
|
+
Async do
|
|
198
|
+
await bot.set_webhook(
|
|
199
|
+
url: "https://#{ENV['DOMAIN']}/webhook/#{bot.token}",
|
|
200
|
+
max_connections: 40
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
server.run
|
|
204
|
+
end
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Docker Deployment
|
|
208
|
+
|
|
209
|
+
```dockerfile
|
|
210
|
+
FROM ruby:3.2-alpine
|
|
211
|
+
WORKDIR /app
|
|
212
|
+
COPY Gemfile Gemfile.lock ./
|
|
213
|
+
RUN bundle install
|
|
214
|
+
COPY . .
|
|
215
|
+
CMD ["ruby", "bot.rb"]
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
๐งช Testing
|
|
221
|
+
|
|
222
|
+
```ruby
|
|
223
|
+
# Unit test scenes
|
|
224
|
+
describe RegistrationScene do
|
|
225
|
+
it "asks for name on enter" do
|
|
226
|
+
ctx = mock_context
|
|
227
|
+
scene = bot.scenes[:registration]
|
|
228
|
+
expect(ctx).to receive(:reply).with("What's your name?")
|
|
229
|
+
scene.enter(ctx)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Integration testing
|
|
234
|
+
bot.command('test') { |ctx| ctx.reply("Working!") }
|
|
235
|
+
|
|
236
|
+
update = mock_update(text: '/test')
|
|
237
|
+
bot.process(update)
|
|
238
|
+
# Verify reply sent
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
๐ฆ Project Structure
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
my_bot/
|
|
247
|
+
โโโ bot.rb # Main bot file
|
|
248
|
+
โโโ Gemfile
|
|
249
|
+
โโโ config/
|
|
250
|
+
โ โโโ initializers/ # Middleware, database setup
|
|
251
|
+
โ โโโ environments/ # Development/production configs
|
|
252
|
+
โโโ lib/
|
|
253
|
+
โ โโโ middleware/ # Custom middleware classes
|
|
254
|
+
โ โโโ scenes/ # Scene definitions
|
|
255
|
+
โ โโโ services/ # Business logic
|
|
256
|
+
โโโ db/ # Database migrations
|
|
257
|
+
โโโ spec/ # Tests
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
๐ค Contributing
|
|
263
|
+
|
|
264
|
+
We love contributions! Whether you're fixing bugs, adding features, or improving documentation, all help is welcome.
|
|
265
|
+
|
|
266
|
+
How to Contribute:
|
|
267
|
+
|
|
268
|
+
1. Read CONTRIBUTING.md for detailed guidelines
|
|
269
|
+
2. Fork the repository on GitLab
|
|
270
|
+
3. Create a feature branch (git checkout -b feature/amazing-thing)
|
|
271
|
+
4. Make your changes and add tests
|
|
272
|
+
5. Run tests (rake spec)
|
|
273
|
+
6. Commit with clear messages (git commit -m 'Add amazing thing')
|
|
274
|
+
7. Push and open a Merge Request
|
|
275
|
+
|
|
276
|
+
Development Setup:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
git clone https://gitlab.com/ruby-telegem/telegem.git
|
|
280
|
+
cd telegem
|
|
281
|
+
bundle install
|
|
282
|
+
rake spec # Run tests
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Need Help?
|
|
286
|
+
|
|
287
|
+
- Issues - Bug reports and feature requests
|
|
288
|
+
- Merge Requests - Code contributions
|
|
289
|
+
- Discussions - Questions and ideas
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
๐ง Roadmap
|
|
294
|
+
|
|
295
|
+
Coming Soon
|
|
296
|
+
|
|
297
|
+
- Plugin System - Community plugins ecosystem
|
|
298
|
+
- More Session Stores - PostgreSQL, MySQL, MongoDB
|
|
299
|
+
- Built-in Analytics - Usage tracking & insights
|
|
300
|
+
- Admin Dashboard - Web interface for bot management
|
|
301
|
+
- i18n Support - Built-in internationalization
|
|
302
|
+
|
|
303
|
+
In Progress
|
|
304
|
+
|
|
305
|
+
- Async Core - Non-blocking I/O
|
|
306
|
+
- Scene System - Multi-step conversations
|
|
307
|
+
- Middleware Pipeline - Extensible architecture
|
|
308
|
+
- Webhook Server - Production deployment
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
๐ License
|
|
313
|
+
|
|
314
|
+
MIT License - see LICENSE.txt for details.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
๐ Acknowledgments
|
|
319
|
+
|
|
320
|
+
- Inspired by Telegraf.js - Amazing Node.js Telegram framework
|
|
321
|
+
- Built on async - Ruby's async I/O gem
|
|
322
|
+
- Thanks to the Telegram team for the excellent Bot API
|
|
323
|
+
- Community - All contributors and users
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
๐ Star History
|
|
328
|
+
|
|
329
|
+
[history](https://api.star-history.com/svg?repos=ruby-telegem/telegem&type=Date)
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
๐ Support & Community
|
|
334
|
+
|
|
335
|
+
- GitLab Issues: Report bugs & request features
|
|
336
|
+
- Examples: Example bots repository
|
|
337
|
+
- Chat: Join our community (Telegram group)
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
๐ Ready to Build?
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
# Start building your bot now!
|
|
345
|
+
gem install telegem
|
|
346
|
+
ruby -r telegem -e "puts 'Welcome to Telegem! ๐'"
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Check out docs/ for comprehensive guides, or jump right into examples/ to see real bots in action!
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
Built with โค๏ธ for the Ruby community. Happy bot building! ๐คโจ
|
|
File without changes
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# Test-Projects/bot_test1.rb
|
|
3
|
+
require 'telegem'
|
|
4
|
+
|
|
5
|
+
puts "๐ Starting Bot Test 1..."
|
|
6
|
+
puts "Ruby: #{RUBY_VERSION}"
|
|
7
|
+
puts "Telegem: #{Telegem::VERSION rescue 'Not loaded'}"
|
|
8
|
+
|
|
9
|
+
begin
|
|
10
|
+
# 1. Create bot with your token
|
|
11
|
+
bot = Telegem.new('8013082846:AAEnG0T1pnLhOpjwpF3I-A4DX4aQy_HPsAc')
|
|
12
|
+
puts "โ
Bot object created"
|
|
13
|
+
|
|
14
|
+
# 2. Add a command
|
|
15
|
+
bot.command('start') do |ctx|
|
|
16
|
+
ctx.reply "๐ค Test Bot 1 is working!"
|
|
17
|
+
puts "โ
Command '/start' would reply"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
bot.command('ping') do |ctx|
|
|
21
|
+
ctx.reply "๐ Pong! #{Time.now}"
|
|
22
|
+
puts "โ
Command '/ping' would reply"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
puts "โ
Commands registered"
|
|
26
|
+
|
|
27
|
+
# 3. Try a simple API call (getMe)
|
|
28
|
+
puts "๐ก Testing API connection..."
|
|
29
|
+
me = bot.api.call('getMe') rescue nil
|
|
30
|
+
|
|
31
|
+
if me
|
|
32
|
+
puts "โ
API Connected! Bot: @#{me['username']} (#{me['first_name']})"
|
|
33
|
+
else
|
|
34
|
+
puts "โ ๏ธ API test failed (might be network/CI issue)"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# 4. Start polling for 10 seconds
|
|
38
|
+
puts "๐ Starting bot polling (10 seconds test)..."
|
|
39
|
+
|
|
40
|
+
# Run polling in a thread with timeout
|
|
41
|
+
polling_thread = Thread.new do
|
|
42
|
+
begin
|
|
43
|
+
bot.start_polling(timeout: 5, limit: 1)
|
|
44
|
+
rescue => e
|
|
45
|
+
puts "โ ๏ธ Polling error (normal in CI): #{e.message}"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Wait 10 seconds then stop
|
|
50
|
+
sleep 10
|
|
51
|
+
puts "โฑ๏ธ 10 seconds passed, stopping bot..."
|
|
52
|
+
|
|
53
|
+
# Try to stop gracefully
|
|
54
|
+
bot.shutdown rescue nil
|
|
55
|
+
polling_thread.kill if polling_thread.alive?
|
|
56
|
+
|
|
57
|
+
puts "๐ Test completed successfully!"
|
|
58
|
+
puts "โ
Bot framework works!"
|
|
59
|
+
puts "โ
Commands work!"
|
|
60
|
+
puts "โ
Async system works!"
|
|
61
|
+
|
|
62
|
+
rescue LoadError => e
|
|
63
|
+
puts "โ LOAD ERROR: #{e.message}"
|
|
64
|
+
puts "Backtrace:"
|
|
65
|
+
puts e.backtrace.first(5)
|
|
66
|
+
exit 1
|
|
67
|
+
|
|
68
|
+
rescue => e
|
|
69
|
+
puts "โ ERROR: #{e.class}: #{e.message}"
|
|
70
|
+
puts "Backtrace (first 3 lines):"
|
|
71
|
+
puts e.backtrace.first(3)
|
|
72
|
+
exit 1
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
puts "โจ All tests passed!"
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
|
|
2
|
+
```ruby
|
|
3
|
+
require 'telegem'
|
|
4
|
+
|
|
5
|
+
# 1. Create bot
|
|
6
|
+
bot = Telegem.new(ENV['PIZZA_BOT_TOKEN'])
|
|
7
|
+
|
|
8
|
+
# 2. Welcome command
|
|
9
|
+
bot.command('start') do |ctx|
|
|
10
|
+
ctx.reply "๐ Welcome to PizzaBot!"
|
|
11
|
+
ctx.reply "Use /order to start ordering"
|
|
12
|
+
ctx.reply "Use /menu to see options"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# 3. Menu command
|
|
16
|
+
bot.command('menu') do |ctx|
|
|
17
|
+
menu = <<~MENU
|
|
18
|
+
*Our Menu:*
|
|
19
|
+
|
|
20
|
+
๐ Pizzas:
|
|
21
|
+
- Margherita: $10
|
|
22
|
+
- Pepperoni: $12
|
|
23
|
+
- Veggie: $11
|
|
24
|
+
|
|
25
|
+
๐ฅค Drinks:
|
|
26
|
+
- Cola: $2
|
|
27
|
+
- Water: $1
|
|
28
|
+
|
|
29
|
+
Use /order to order!
|
|
30
|
+
MENU
|
|
31
|
+
|
|
32
|
+
ctx.reply menu, parse_mode: 'Markdown'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# 4. Order command - Starts a scene
|
|
36
|
+
bot.scene :ordering do
|
|
37
|
+
step :choose_pizza do |ctx|
|
|
38
|
+
keyboard = ctx.keyboard do
|
|
39
|
+
row "Margherita", "Pepperoni"
|
|
40
|
+
row "Veggie", "Cancel"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
ctx.reply "Choose your pizza:", reply_markup: keyboard
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
step :save_pizza do |ctx|
|
|
47
|
+
ctx.session[:pizza] = ctx.message.text
|
|
48
|
+
ctx.reply "Great! #{ctx.session[:pizza]} selected."
|
|
49
|
+
ctx.reply "What's your address?"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
step :save_address do |ctx|
|
|
53
|
+
ctx.session[:address] = ctx.message.text
|
|
54
|
+
|
|
55
|
+
# Show summary
|
|
56
|
+
summary = <<~SUMMARY
|
|
57
|
+
*Order Summary:*
|
|
58
|
+
|
|
59
|
+
Pizza: #{ctx.session[:pizza]}
|
|
60
|
+
Address: #{ctx.session[:address]}
|
|
61
|
+
|
|
62
|
+
Confirm? (Yes/No)
|
|
63
|
+
SUMMARY
|
|
64
|
+
|
|
65
|
+
ctx.reply summary, parse_mode: 'Markdown'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
step :confirm do |ctx|
|
|
69
|
+
if ctx.message.text.downcase == 'yes'
|
|
70
|
+
ctx.reply "โ
Order placed! Delivery in 30 minutes."
|
|
71
|
+
ctx.reply "Use /track to track your order"
|
|
72
|
+
else
|
|
73
|
+
ctx.reply "โ Order cancelled."
|
|
74
|
+
end
|
|
75
|
+
ctx.leave_scene
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Handle "Cancel" at any step
|
|
79
|
+
on_enter do |ctx|
|
|
80
|
+
ctx.session[:order_id] = rand(1000..9999)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# 5. Start the order scene
|
|
85
|
+
bot.command('order') do |ctx|
|
|
86
|
+
ctx.enter_scene(:ordering)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# 6. Track order (simple version)
|
|
90
|
+
bot.command('track') do |ctx|
|
|
91
|
+
if ctx.session[:order_id]
|
|
92
|
+
ctx.reply "Order ##{ctx.session[:order_id]} is being prepared!"
|
|
93
|
+
else
|
|
94
|
+
ctx.reply "No active order. Use /order to start."
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# 7. Handle keyboard button presses
|
|
99
|
+
bot.on(:message) do |ctx|
|
|
100
|
+
# Skip if it's a command or in scene
|
|
101
|
+
next if ctx.message.command? || ctx.scene
|
|
102
|
+
|
|
103
|
+
text = ctx.message.text
|
|
104
|
+
|
|
105
|
+
case text
|
|
106
|
+
when "Margherita", "Pepperoni", "Veggie"
|
|
107
|
+
ctx.reply "Use /order to order a #{text} pizza!"
|
|
108
|
+
when "Cancel"
|
|
109
|
+
ctx.reply "Cancelled."
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# 8. Start bot
|
|
114
|
+
if ENV['WEBHOOK']
|
|
115
|
+
bot.webhook_server(port: ENV['PORT'] || 3000).run
|
|
116
|
+
else
|
|
117
|
+
puts "๐ PizzaBot starting..."
|
|
118
|
+
bot.start_polling
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
๐งช Let's Test It!
|
|
125
|
+
|
|
126
|
+
Create the file:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
mkdir -p examples
|
|
130
|
+
touch examples/pizza_bot.rb
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Run it:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Set your token
|
|
137
|
+
export PIZZA_BOT_TOKEN="123456:your_token_here"
|
|
138
|
+
|
|
139
|
+
# Run the bot
|
|
140
|
+
ruby examples/pizza_bot.rb
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Test the flow:
|
|
144
|
+
|
|
145
|
+
1. /start โ Shows welcome
|
|
146
|
+
2. /menu โ Shows pizza menu
|
|
147
|
+
3. /order โ Starts ordering scene
|
|
148
|
+
4. Choose "Margherita" โ Asks for address
|
|
149
|
+
5. Type your address โ Shows summary
|
|
150
|
+
6. Type "yes" โ Order confirmed!
|
|
151
|
+
7. /track โ Shows order status
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
๐๏ธ Your Homework:
|
|
156
|
+
|
|
157
|
+
Can you add:
|
|
158
|
+
|
|
159
|
+
1. A /help command showing all commands?
|
|
160
|
+
2. A "size" step in the scene (Small/Medium/Large)?
|
|
161
|
+
3. A middleware that logs all orders to a file?
|
|
162
|
+
|
|
163
|
+
This is how you learn: Build, break, fix, improve. You now understand then library enough to code without AI help!
|
data/docs/.gitkeep
ADDED
|
File without changes
|