telegem 2.0.8 → 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 +3 -0
  24. data/lib/core/bot.rb +31 -27
  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
@@ -0,0 +1,210 @@
1
+ class WatchHandler
2
+ def initialize(bot, db)
3
+ @bot = bot
4
+ @db = db
5
+ setup_watch_commands
6
+ setup_inline_handlers
7
+ end
8
+
9
+ def setup_watch_commands
10
+ # Command: /watch - Show all subscribed shows with inline buttons
11
+ @bot.command("watch") do |ctx|
12
+ show_watch_menu(ctx)
13
+ end
14
+
15
+ # Command: /watched <show_id> s<season>e<episode>
16
+ @bot.command("watched") do |ctx|
17
+ handle_watched_command(ctx)
18
+ end
19
+ end
20
+
21
+ def show_watch_menu(ctx)
22
+ user_id = ctx.from.id
23
+
24
+ # Get user's shows with their current progress
25
+ shows = @db.execute(<<-SQL, [user_id])
26
+ SELECT
27
+ movies.id,
28
+ movies.title,
29
+ watched.season as current_season,
30
+ watched.episode as current_episode
31
+ FROM watched
32
+ JOIN movies ON movies.id = watched.movie_id
33
+ WHERE watched.telegram_id = ?
34
+ ORDER BY movies.title
35
+ SQL
36
+
37
+ if shows.empty?
38
+ ctx.reply("📭 You're not tracking any shows yet!\nUse /search to find shows, then /add <id>")
39
+ return
40
+ end
41
+
42
+ # Create message with inline keyboard
43
+ message = "📺 *Mark Episodes Watched*\n\n"
44
+ message += "Click a show to mark episodes:\n\n"
45
+
46
+ shows.each do |id, title, season, episode|
47
+ message += "🎬 *#{title}*\n"
48
+ message += " Current: S#{season}E#{episode}\n"
49
+ message += " Next: S#{season}E#{episode + 1}\n\n"
50
+ end
51
+
52
+ # Create inline keyboard with ONE button per show
53
+ inline = Telegem.inline do
54
+ shows.each do |id, title, season, episode|
55
+ # Button shows: "Stranger Things (S1E3)"
56
+ row button "#{title} (S#{season}E#{episode})",
57
+ callback_data: "select_show:#{id}:#{season}:#{episode}"
58
+ end
59
+ # Add a "Mark All Caught Up" button
60
+ row button "✅ Mark All As Caught Up", callback_data: "catchup_all"
61
+ end
62
+
63
+ ctx.reply(message, reply_markup: inline, parse_mode: 'Markdown')
64
+ end
65
+
66
+ def setup_inline_handlers
67
+ @bot.on(:callback_query) do |ctx|
68
+ case ctx.data
69
+ when /^select_show:(\d+):(\d+):(\d+)$/
70
+ handle_show_selection(ctx, $1.to_i, $2.to_i, $3.to_i)
71
+ when /^mark_episode:(\d+):(\d+):(\d+)$/
72
+ handle_mark_episode(ctx, $1.to_i, $2.to_i, $3.to_i)
73
+ when "catchup_all"
74
+ handle_catchup_all(ctx)
75
+ when "back_to_shows"
76
+ show_watch_menu(ctx)
77
+ end
78
+ end
79
+ end
80
+
81
+ def handle_show_selection(ctx, show_id, current_season, current_episode)
82
+ # Get show title
83
+ show = @db.execute(
84
+ "SELECT title FROM movies WHERE id = ?",
85
+ [show_id]
86
+ ).first
87
+
88
+ return unless show
89
+
90
+ show_title = show[0]
91
+
92
+ # Create episode selection buttons
93
+ message = "🎬 *#{show_title}*\n"
94
+ message += "Mark which episode you watched:\n\n"
95
+ message += "Current: S#{current_season}E#{current_episode}\n\n"
96
+
97
+ # Create buttons for next 5 episodes
98
+ inline = Telegem.inline do
99
+ # Show 5 episodes: current+1 to current+5
100
+ (1..5).each do |offset|
101
+ ep_num = current_episode + offset
102
+ row button "✅ S#{current_season}E#{ep_num}",
103
+ callback_data: "mark_episode:#{show_id}:#{current_season}:#{ep_num}"
104
+ end
105
+
106
+ # Next season button
107
+ row button "➡️ Next Season (S#{current_season + 1}E1)",
108
+ callback_data: "mark_episode:#{show_id}:#{current_season + 1}:1"
109
+
110
+ # Back button
111
+ row button "🔙 Back to Shows", callback_data: "back_to_shows"
112
+ end
113
+
114
+ # Edit the message with new buttons
115
+ ctx.edit_message_text(message, reply_markup: inline, parse_mode: 'Markdown')
116
+ ctx.answer_callback_query(text: "Select episode for #{show_title}")
117
+ end
118
+
119
+ def handle_mark_episode(ctx, show_id, season, episode)
120
+ user_id = ctx.from.id
121
+
122
+ # Update watched table
123
+ @db.execute(<<-SQL, [season, episode, user_id, show_id])
124
+ UPDATE watched
125
+ SET season = ?, episode = ?, updated_at = CURRENT_TIMESTAMP
126
+ WHERE telegram_id = ? AND movie_id = ?
127
+ SQL
128
+
129
+ # Get show title for response
130
+ show = @db.execute(
131
+ "SELECT title FROM movies WHERE id = ?",
132
+ [show_id]
133
+ ).first
134
+
135
+ show_title = show[0] if show
136
+
137
+ # Show confirmation
138
+ ctx.answer_callback_query(
139
+ text: "✅ Marked #{show_title} S#{season}E#{episode} as watched!"
140
+ )
141
+
142
+ # Update message to show new status
143
+ message = "✅ *Updated!*\n\n"
144
+ message += "🎬 #{show_title}\n"
145
+ message += "Now watching: S#{season}E#{episode}\n"
146
+ message += "Next alert: S#{season}E#{episode + 1}\n\n"
147
+ message += "Click another show or use /watch again."
148
+
149
+ # Keep back button
150
+ inline = Telegem.inline do
151
+ row button "🔙 Back to Shows", callback_data: "back_to_shows"
152
+ end
153
+
154
+ ctx.edit_message_text(message, reply_markup: inline, parse_mode: 'Markdown')
155
+ end
156
+
157
+ def handle_catchup_all(ctx)
158
+ user_id = ctx.from.id
159
+
160
+ # For each show, set episode to a high number (like 999 to mark as "caught up")
161
+ shows_updated = @db.execute(<<-SQL, [user_id])
162
+ UPDATE watched
163
+ SET episode = 999, updated_at = CURRENT_TIMESTAMP
164
+ WHERE telegram_id = ? AND episode < 999
165
+ SQL
166
+
167
+ ctx.answer_callback_query(
168
+ text: "✅ Marked all shows as caught up!"
169
+ )
170
+
171
+ # Go back to show list
172
+ show_watch_menu(ctx)
173
+ end
174
+
175
+ def handle_watched_command(ctx)
176
+ # Text command version: /watched 1 s1e3
177
+ args = ctx.message.text.split
178
+
179
+ if args.size != 3
180
+ ctx.reply("Usage: /watched <show_id> <episode>\nExample: /watched 1 s1e3")
181
+ return
182
+ end
183
+
184
+ show_id = args[1].to_i
185
+ episode_str = args[2]
186
+
187
+ match = episode_str.match(/s(\d+)e(\d+)/i)
188
+ unless match
189
+ ctx.reply("❌ Invalid format. Use: s1e3, s2e5, etc.")
190
+ return
191
+ end
192
+
193
+ season = match[1].to_i
194
+ episode = match[2].to_i
195
+ user_id = ctx.from.id
196
+
197
+ # Update database
198
+ @db.execute(<<-SQL, [season, episode, user_id, show_id])
199
+ UPDATE watched
200
+ SET season = ?, episode = ?, updated_at = CURRENT_TIMESTAMP
201
+ WHERE telegram_id = ? AND movie_id = ?
202
+ SQL
203
+
204
+ if @db.changes > 0
205
+ ctx.reply("✅ Updated! You've watched up to S#{season}E#{episode}")
206
+ else
207
+ ctx.reply("❌ You're not tracking that show. Use /add first.")
208
+ end
209
+ end
210
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ #marvel
2
+
3
+ - https://gitlab.com/ynwghosted/bot-test/-/tree/main/editor/src
data/docs-src/.gitkeep ADDED
File without changes
Binary file
data/docs-src/bot.md ADDED
@@ -0,0 +1,295 @@
1
+
2
+ # Bot API Reference
3
+
4
+ The `Telegem::Core::Bot` class is the main controller for your Telegram bot.
5
+
6
+ ## Instantiation
7
+
8
+ ```ruby
9
+ bot = Telegem.new(token, **options)
10
+ # or
11
+ bot = Telegem::Core::Bot.new(token, **options)
12
+ ```
13
+
14
+ Bot Control Methods
15
+
16
+ start_polling(**options)
17
+
18
+ Starts the bot in long-polling mode (for development/local use).
19
+
20
+ ```ruby
21
+ bot.start_polling(
22
+ timeout: 30, # Seconds to wait for updates (default: 30)
23
+ limit: 100, # Max updates per request (default: 100)
24
+ allowed_updates: ['message', 'callback_query'] # Filter updates
25
+ )
26
+ ```
27
+
28
+ shutdown()
29
+
30
+ Gracefully stops the bot.
31
+
32
+ ```ruby
33
+ bot.shutdown # Stops polling, closes connections, terminates workers
34
+ ```
35
+
36
+ running?()
37
+
38
+ Checks if the bot is currently active.
39
+
40
+ ```ruby
41
+ if bot.running?
42
+ puts "Bot is online"
43
+ else
44
+ puts "Bot is offline"
45
+ end
46
+ ```
47
+
48
+ Handler Registration Methods
49
+
50
+ command(name, **options, &block)
51
+
52
+ Registers a command handler.
53
+
54
+ ```ruby
55
+ bot.command('start') do |ctx|
56
+ ctx.reply "Welcome! Use /help for commands."
57
+ end
58
+
59
+ # With arguments
60
+ bot.command('greet') do |ctx|
61
+ name = ctx.command_args || 'friend'
62
+ ctx.reply "Hello, #{name}!"
63
+ end
64
+ ```
65
+
66
+ hears(pattern, **options, &block)
67
+
68
+ Registers a text pattern handler.
69
+
70
+ ```ruby
71
+ # Regex pattern
72
+ bot.hears(/hello|hi|hey/i) do |ctx|
73
+ ctx.reply "Hello there! 👋"
74
+ end
75
+
76
+ # Exact match
77
+ bot.hears('ping') do |ctx|
78
+ ctx.reply 'pong 🏓'
79
+ end
80
+ ```
81
+
82
+ on(type, filters = {}, &block)
83
+
84
+ Generic update handler.
85
+
86
+ ```ruby
87
+ # Message types
88
+ bot.on(:message, photo: true) do |ctx|
89
+ ctx.reply "Nice photo! 📸"
90
+ end
91
+
92
+ bot.on(:message, location: true) do |ctx|
93
+ ctx.reply "Thanks for sharing your location! 📍"
94
+ end
95
+
96
+ # Callback queries (inline button clicks)
97
+ bot.on(:callback_query) do |ctx|
98
+ ctx.answer_callback_query(text: "You clicked #{ctx.data}")
99
+ end
100
+
101
+ # Filter by chat type
102
+ bot.on(:message, chat_type: 'private') do |ctx|
103
+ ctx.reply "This is a private chat"
104
+ end
105
+ ```
106
+
107
+ Middleware System
108
+
109
+ use(middleware, *args, &block)
110
+
111
+ Adds middleware to the processing chain.
112
+
113
+ ```ruby
114
+ # Built-in session middleware (auto-added)
115
+ bot.use(Telegem::Session::Middleware)
116
+
117
+ # Custom middleware
118
+ class LoggerMiddleware
119
+ def call(ctx, next_middleware)
120
+ puts "Processing update from #{ctx.from.id}"
121
+ next_middleware.call(ctx)
122
+ end
123
+ end
124
+
125
+ bot.use(LoggerMiddleware)
126
+ ```
127
+
128
+ Scene System
129
+
130
+ scene(id, &block)
131
+
132
+ Defines a scene (multi-step conversation).
133
+
134
+ ```ruby
135
+ bot.scene(:survey) do |scene|
136
+ scene.step(:start) do |ctx|
137
+ ctx.reply "What's your name?"
138
+ ctx.session[:step] = :name
139
+ end
140
+
141
+ scene.step(:name) do |ctx|
142
+ name = ctx.message.text
143
+ ctx.reply "Hello #{name}! How old are you?"
144
+ ctx.session[:name] = name
145
+ ctx.session[:step] = :age
146
+ end
147
+ end
148
+
149
+ # Enter scene from command
150
+ bot.command('survey') do |ctx|
151
+ ctx.enter_scene(:survey)
152
+ end
153
+ ```
154
+
155
+ Webhook Methods
156
+
157
+ webhook(**options)
158
+
159
+ Returns a webhook server instance.
160
+
161
+ ```ruby
162
+ # Quick setup (auto-detects cloud platform)
163
+ server = bot.webhook.run
164
+
165
+ # Manual configuration
166
+ server = bot.webhook(
167
+ port: 3000,
168
+ host: '0.0.0.0',
169
+ secret_token: ENV['SECRET_TOKEN'],
170
+ logger: Logger.new('webhook.log')
171
+ )
172
+ server.run
173
+ server.set_webhook
174
+ ```
175
+
176
+ set_webhook(url, **options)
177
+
178
+ Manually sets webhook URL.
179
+
180
+ ```ruby
181
+ bot.set_webhook(
182
+ 'https://your-app.herokuapp.com/webhook',
183
+ secret_token: 'your-secret',
184
+ drop_pending_updates: true
185
+ )
186
+ ```
187
+
188
+ delete_webhook()
189
+
190
+ Removes webhook configuration.
191
+
192
+ ```ruby
193
+ bot.delete_webhook # Switch back to polling
194
+ ```
195
+
196
+ get_webhook_info()
197
+
198
+ Gets current webhook information.
199
+
200
+ ```ruby
201
+ info = bot.get_webhook_info
202
+ puts "Webhook URL: #{info['url']}"
203
+ puts "Has custom certificate: #{info['has_custom_certificate']}"
204
+ ```
205
+
206
+ Error Handling
207
+
208
+ error(&block)
209
+
210
+ Sets global error handler.
211
+
212
+ ```ruby
213
+ bot.error do |error, ctx|
214
+ puts "Error: #{error.message}"
215
+ puts "Context: User #{ctx.from&.id}, Chat #{ctx.chat&.id}"
216
+
217
+ # Send error to user
218
+ ctx.reply "Something went wrong! 😅" if ctx&.chat
219
+ end
220
+ ```
221
+
222
+ Update Processing
223
+
224
+ process(update_data)
225
+
226
+ Manually process an update (useful for testing).
227
+
228
+ ```ruby
229
+ test_update = {
230
+ 'update_id' => 1,
231
+ 'message' => {
232
+ 'message_id' => 1,
233
+ 'from' => {'id' => 123, 'first_name' => 'Test'},
234
+ 'chat' => {'id' => 123},
235
+ 'date' => Time.now.to_i,
236
+ 'text' => '/start'
237
+ }
238
+ }
239
+
240
+ bot.process(test_update)
241
+ ```
242
+
243
+ Bot Options
244
+
245
+ Available options when creating bot:
246
+
247
+ ```ruby
248
+ bot = Telegem.new('TOKEN',
249
+ logger: Logger.new('bot.log'), # Custom logger
250
+ timeout: 60, # API timeout in seconds
251
+ max_threads: 20, # Worker thread pool size
252
+ worker_count: 5, # Update processing workers
253
+ session_store: custom_store # Custom session storage
254
+ )
255
+ ```
256
+
257
+ Complete Example
258
+
259
+ ```ruby
260
+ require 'telegem'
261
+
262
+ bot = Telegem.new(ENV['BOT_TOKEN'])
263
+
264
+ # Error handling
265
+ bot.error do |error, ctx|
266
+ puts "Error: #{error.class}: #{error.message}"
267
+ end
268
+
269
+ # Commands
270
+ bot.command('start') { |ctx| ctx.reply "Welcome!" }
271
+ bot.command('help') { |ctx| ctx.reply "Available: /start, /help, /menu" }
272
+
273
+ # Interactive menu
274
+ bot.command('menu') do |ctx|
275
+ keyboard = Telegem.keyboard do
276
+ row "Option 1", "Option 2"
277
+ row "Cancel"
278
+ end
279
+ ctx.reply "Choose:", reply_markup: keyboard
280
+ end
281
+
282
+ # Start based on environment
283
+ if ENV['RACK_ENV'] == 'production'
284
+ bot.webhook.run
285
+ else
286
+ bot.start_polling
287
+ end
288
+ ```
289
+
290
+ ---
291
+
292
+ Next: Context Methods | Keyboard API
293
+
294
+ ```
295
+ ```