telegem 3.0.3 → 3.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc9031982499124e1b520cde96b341b071a695917a57804cd9375d513dcf4bf1
4
- data.tar.gz: d8b52c0273d048631d8858c5e098e070ac947f3fac222e6c20eb787b69663b59
3
+ metadata.gz: 9e796af1eab96fc25ece5e1dfdd0913451f66087d3181ae54f7375b10be4ebfa
4
+ data.tar.gz: e7fdc50d3d8e1bcb570fdb03bd0e301ddcbae3702f4e03a40ba06e12fc0941f5
5
5
  SHA512:
6
- metadata.gz: c442335bb33c72fad402ccc1dd1a8a759b6dbd44542794f5413eb9b7cb8966909a2075668adc0b3323a14b66a317d4301d93ff3723d9b6424c6a00656fcf8028
7
- data.tar.gz: 298852f385e908d858d4a19e464fdda29b54647fac22e4080a965c0d237b71e39c7d699e26060612682895a676a8fa0ca7a1286a47ef53870d0588f60b8b7916
6
+ metadata.gz: 5719f4e1d5d4ef7c865c3a08abc459712637e24a33d98d954c546a442c70a473878e501ef15f44714c1f574802325940f2d2431b863c07c353a19484e5852da5
7
+ data.tar.gz: 36035a791dca055bb171003ab43e6e0229de75dee1ec02fd5d61cd0b0e8c97f9e385b221333a68f2f6867ad9912c4faf63b3eaaf070b4a59c614e13bd33d1a17
data/CHANGELOG ADDED
@@ -0,0 +1,15 @@
1
+ ## v3.0.4 (2026-01-17)
2
+
3
+ ### Fixed
4
+ - **Critical**: Fixed `NoMethodError: undefined method 'wait'` for HTTPX responses
5
+ - Unified HTTPX client usage across all API methods
6
+ - Proper async/await pattern implementation
7
+ - Improved error handling for network timeouts
8
+
9
+ ### Changed
10
+ - `API::Client#call` now uses async/await instead of blocking `.wait`
11
+ - Better timeout handling for all Telegram API calls
12
+
13
+ ### Notes
14
+ - This release fixes compatibility with HTTPX >= 0.23.0
15
+ - All async operations now use `.await` instead of deprecated `.wait`
data/examples/.gitkeep ADDED
File without changes
data/lib/api/client.rb CHANGED
@@ -27,26 +27,12 @@ module Telegem
27
27
  }
28
28
  )
29
29
  end
30
- def call(method, params = {})
31
- url = "#{BASE_URL}/bot#{@token}/#{method}"
32
- @logger.debug("API Call: #{method}") if @logger
33
-
34
- http_sync = HTTPX.with(
35
- timeout: {
36
- request_timeout: 30,
37
- connect_timeout: 10,
38
- write_timeout: 10,
39
- read_timeout: 30
40
- },
41
- headers: {
42
- 'Content-Type' => 'application/json',
43
- 'User-Agent' => "Telegem/#{Telegem::VERSION}"
44
- }
45
- )
46
-
47
- response = http_sync.post(url, json: params.compact).wait
48
- response.json
49
- end
30
+ def call(method, params = {})
31
+ url = "#{BASE_URL}/bot#{@token}/#{method}"
32
+ @logger.debug("Api call #{method}") if @logger
33
+ response = @http.post(url, json: params.compact).await
34
+ response.json
35
+ end
50
36
  def call!(method, params = {}, &callback)
51
37
  url = "#{BASE_URL}/bot#{@token}/#{method}"
52
38
 
@@ -112,8 +98,8 @@ end
112
98
  [key.to_s, value.to_s]
113
99
  end
114
100
  end
115
-
116
- @http.post(url, form: form)
101
+ response = @http.post(url, form: form).await
102
+ response.json
117
103
  end
118
104
 
119
105
  def get_updates(offset: nil, timeout: 30, limit: 100, allowed_updates: nil)
data/lib/core/bot.rb CHANGED
@@ -19,7 +19,13 @@ module Telegem
19
19
  chat_member: [],
20
20
  poll: [],
21
21
  pre_checkout_query: [],
22
- shipping_query: []
22
+ shipping_query: [],
23
+ poll_answer: [],
24
+ chat_join_request: [],
25
+ chat_boost: [],
26
+ removed_chat_boost: [],
27
+ message_reaction: [],
28
+ message_reaction_count: []
23
29
  }
24
30
 
25
31
  @middleware = []
@@ -69,6 +75,71 @@ module Telegem
69
75
  end
70
76
  end
71
77
 
78
+ def contact(**options, &block)
79
+ on(:message, contact: true) do |ctx|
80
+ block.call(ctx)
81
+ end
82
+ end
83
+
84
+ def poll_answer(&block)
85
+ on(:poll_answer) do |ctx|
86
+ block.call(ctx)
87
+ end
88
+ end
89
+
90
+ def pre_checkout_query(&block)
91
+ on(:pre_checkout_query) do |ctx|
92
+ block.call(ctx)
93
+ end
94
+ end
95
+
96
+ def shipping_query(&block)
97
+ on(:shipping_query) do |ctx|
98
+ block.call(ctx)
99
+ end
100
+ end
101
+
102
+ def chat_join_request(&block)
103
+ on(:chat_join_request) do |ctx|
104
+ block.call(ctx)
105
+ end
106
+ end
107
+
108
+ def chat_boost(&block)
109
+ on(:chat_boost) do |ctx|
110
+ block.call(ctx)
111
+ end
112
+ end
113
+
114
+ def removed_chat_boost(&block)
115
+ on(:removed_chat_boost) do |ctx|
116
+ block.call(ctx)
117
+ end
118
+ end
119
+
120
+ def message_reaction(&block)
121
+ on(:message_reaction) do |ctx|
122
+ block.call(ctx)
123
+ end
124
+ end
125
+
126
+ def message_reaction_count(&block)
127
+ on(:message_reaction_count) do |ctx|
128
+ block.call(ctx)
129
+ end
130
+ end
131
+ def web_app_data(&block)
132
+ on(:message, web_app_data: true) do |ctx|
133
+ block.call(ctx)
134
+ end
135
+ end
136
+
137
+ def location(&block)
138
+ on(:message, location: true) do |ctx|
139
+ block.call(ctx)
140
+ end
141
+ end
142
+
72
143
  def on(type, filters = {}, &block)
73
144
  @handlers[type] << { filters: filters, handler: block }
74
145
  end
@@ -240,6 +311,12 @@ module Telegem
240
311
  return :poll if update.poll
241
312
  return :pre_checkout_query if update.pre_checkout_query
242
313
  return :shipping_query if update.shipping_query
314
+ return :poll_answer if update.poll_answer
315
+ return :chat_join_request if update.chat_join_request
316
+ return :chat_boost if update.chat_boost
317
+ return :removed_chat_boost if update.removed_chat_boost
318
+ return :message_reaction if update.message_reaction
319
+ return :message_reaction_count if update.message_reaction_count
243
320
  :unknown
244
321
  end
245
322
 
@@ -254,10 +331,20 @@ module Telegem
254
331
  matches_chat_type_filter(ctx, value)
255
332
  when :command
256
333
  matches_command_filter(ctx, value)
257
- else
334
+ when :location
335
+ ctx.message&.location != nil
336
+ when :contact
337
+ ctx.message&.contact != nil
338
+ when :web_app_data
339
+ ctx.message&.web_app_data != nil
340
+ else
341
+ if ctx.update.respond_to?(key)
258
342
  ctx.update.send(key) == value
259
- end
260
- end
343
+ else
344
+ false
345
+ end
346
+ end
347
+ end
261
348
  end
262
349
 
263
350
  def matches_text_filter(ctx, pattern)
data/lib/telegem.rb CHANGED
@@ -3,7 +3,7 @@ require 'logger'
3
3
  require 'json'
4
4
 
5
5
  module Telegem
6
- VERSION = "3.0.3".freeze
6
+ VERSION = "3.0.4".freeze
7
7
  end
8
8
 
9
9
  # Load core components
@@ -80,4 +80,4 @@ if ENV['TELEGEM_GLOBAL'] == 'true'
80
80
  def Telegem(token, **options)
81
81
  ::Telegem.new(token, **options)
82
82
  end
83
- end
83
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: telegem
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - sick_phantom
@@ -173,14 +173,13 @@ extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
175
  - ".replit"
176
+ - CHANGELOG
176
177
  - Contributing.md
177
178
  - Gemfile
178
179
  - Gemfile.lock
179
180
  - LICENSE
180
181
  - Readme.md
181
182
  - Starts_HallofFame.md
182
- - Test-Projects/bot.md
183
- - Test-Projects/bot1.rb
184
183
  - bin/.gitkeep
185
184
  - bin/telegem-ssl
186
185
  - docs-src/.gitkeep
@@ -192,6 +191,7 @@ files:
192
191
  - docs-src/keyboard_inline.md
193
192
  - docs-src/scene.md
194
193
  - docs-src/webhook.md
194
+ - examples/.gitkeep
195
195
  - lib/api/client.rb
196
196
  - lib/api/types.rb
197
197
  - lib/core/bot.rb
@@ -206,7 +206,6 @@ files:
206
206
  - lib/webhook/.gitkeep
207
207
  - lib/webhook/server.rb
208
208
  - public/.gitkeep
209
- - public/index.html
210
209
  homepage: https://gitlab.com/ruby-telegem/telegem
211
210
  licenses:
212
211
  - MIT
@@ -217,7 +216,7 @@ metadata:
217
216
  bug_tracker_uri: https://gitlab.com/ruby-telegem/telegem/-/issues
218
217
  documentation_uri: https://gitlab.com/ruby-telegem/telegem/-/tree/main/docs-src?ref_type=heads
219
218
  rubygems_mfa_required: 'false'
220
- post_install_message: "Thanks for installing Telegem 3.0.3!\n\n\U0001F4DA Documentation:
219
+ post_install_message: "Thanks for installing Telegem 3.0.4!\n\n\U0001F4DA Documentation:
221
220
  https://gitlab.com/ruby-telegem/telegem\n\n\U0001F510 For SSL Webhooks:\nRun: telegem-ssl
222
221
  your-domain.com\nThis sets up Let's Encrypt certificates automatically.\n\n\U0001F916
223
222
  Happy bot building!\n"
data/Test-Projects/bot.md DELETED
@@ -1,145 +0,0 @@
1
- bot1.md - Telegem Response Patterns
2
-
3
- How Telegem Returns API Responses
4
-
5
- All ctx methods return HTTPX::Response objects, not JSON hashes.
6
-
7
- Pattern 1: Fire-and-Forget
8
-
9
- ```ruby
10
- ctx.reply("Hello!")
11
- ctx.photo("image.jpg")
12
- ```
13
-
14
- Pattern 2: Get Message ID
15
-
16
- ```ruby
17
- response = ctx.reply("Sending...")
18
-
19
- if response && response.status == 200
20
- data = response.json
21
- if data && data['ok']
22
- message_id = data['result']['message_id']
23
- ctx.session[:msg_id] = message_id
24
- end
25
- end
26
- ```
27
-
28
- Pattern 3: Check for Errors
29
-
30
- ```ruby
31
- response = ctx.reply("Testing...")
32
-
33
- if response && response.status != 200
34
- error = response.json rescue nil
35
- error_msg = error['description'] if error
36
- ctx.reply("Failed: #{error_msg}")
37
- end
38
- ```
39
-
40
- Pattern 4: Edit Messages
41
-
42
- ```ruby
43
- edit_response = ctx.edit_message_text(
44
- "Updated!",
45
- message_id: ctx.session[:msg_id]
46
- )
47
-
48
- if edit_response && edit_response.status == 200
49
- ctx.reply("Edit succeeded!")
50
- end
51
- ```
52
-
53
- Pattern 5: Send Media
54
-
55
- ```ruby
56
- photo_response = ctx.photo(
57
- "https://example.com/image.jpg",
58
- caption: "My photo"
59
- )
60
-
61
- if photo_response && photo_response.status == 200
62
- ctx.reply("Photo sent!")
63
- end
64
- ```
65
-
66
- Pattern 6: Handle Callbacks
67
-
68
- ```ruby
69
- bot.on(:callback_query) do |ctx|
70
- ctx.answer_callback_query(text: "Clicked: #{ctx.data}")
71
-
72
- if ctx.data == 'test'
73
- ctx.edit_message_text("Updated after click!")
74
- end
75
- end
76
- ```
77
-
78
- Pattern 7: Error Wrapping
79
-
80
- ```ruby
81
- begin
82
- response = ctx.reply(some_text)
83
- # Process response
84
- rescue => e
85
- ctx.reply("Error: #{e.message}")
86
- end
87
- ```
88
-
89
- Complete bot1.rb Explained
90
-
91
- Setup
92
-
93
- ```ruby
94
- require 'telegem'
95
- require 'dotenv/load'
96
- bot = Telegem.new(ENV['BOT_TOKEN'])
97
- ```
98
-
99
- /start Command
100
-
101
- Sends welcome, stores message ID in session.
102
-
103
- /help Command
104
-
105
- Simple reply with command list.
106
-
107
- /edit Command
108
-
109
- Edits the stored message, checks edit response.
110
-
111
- /photo Command
112
-
113
- Sends photo, confirms delivery.
114
-
115
- /error Command
116
-
117
- Demonstrates error handling.
118
-
119
- Callback Handler
120
-
121
- Answers inline button clicks.
122
-
123
- Startup Logic
124
-
125
- ```ruby
126
- if ENV['RACK_ENV'] == 'production'
127
- # Webhook mode
128
- server = bot.webhook(port: ENV['PORT'] || 3000)
129
- server.run
130
- server.set_webhook
131
- else
132
- # Polling mode (development)
133
- bot.start_polling(timeout: 30, limit: 100)
134
- end
135
- ```
136
-
137
- Key Takeaways
138
-
139
- 1. Always check response.status (200 = success)
140
- 2. Call .json to get data from response
141
- 3. Check data['ok'] before using result
142
- 4. Store message_id for later editing
143
- 5. Wrap in begin/rescue for network issues
144
-
145
- This pattern ensures your bot handles all API scenarios correctly.
@@ -1,91 +0,0 @@
1
- require 'telegem'
2
- require 'dotenv/load'
3
-
4
- bot = Telegem.new(ENV['BOT_TOKEN'])
5
-
6
- bot.command('start') do |ctx|
7
- ctx.reply("Welcome! Use /help for commands.")
8
-
9
- response = ctx.reply("Processing your request...")
10
-
11
- if response && response.status == 200
12
- data = response.json
13
- if data && data['ok']
14
- ctx.session[:start_msg_id] = data['result']['message_id']
15
- end
16
- end
17
- end
18
-
19
- bot.command('help') do |ctx|
20
- help_text = <<~HELP
21
- Available commands:
22
- /start - Start the bot
23
- /help - This help message
24
- /edit - Edit the start message
25
- /error - Test error handling
26
- /photo - Send a photo
27
- HELP
28
-
29
- ctx.reply(help_text)
30
- end
31
-
32
- bot.command('edit') do |ctx|
33
- if ctx.session[:start_msg_id]
34
- edit_response = ctx.edit_message_text(
35
- "✅ Updated at #{Time.now.strftime('%H:%M:%S')}",
36
- message_id: ctx.session[:start_msg_id]
37
- )
38
-
39
- if edit_response && edit_response.status == 200
40
- ctx.reply("Message edited successfully!")
41
- else
42
- status = edit_response ? edit_response.status : 'no response'
43
- ctx.reply("Edit failed (status: #{status})")
44
- end
45
- else
46
- ctx.reply("Send /start first to create a message to edit.")
47
- end
48
- end
49
-
50
- bot.command('photo') do |ctx|
51
- photo_response = ctx.photo(
52
- "https://picsum.photos/400/300",
53
- caption: "Random image - #{Time.now.strftime('%H:%M:%S')}"
54
- )
55
-
56
- if photo_response && photo_response.status == 200
57
- ctx.reply("Photo sent successfully!")
58
- else
59
- ctx.reply("Failed to send photo.")
60
- end
61
- end
62
-
63
- bot.command('error') do |ctx|
64
- begin
65
- invalid_response = ctx.reply(nil)
66
-
67
- if invalid_response && invalid_response.status != 200
68
- error_data = invalid_response.json rescue nil
69
- error_msg = error_data ? error_data['description'] : "Unknown error"
70
- ctx.reply("API Error: #{error_msg}")
71
- end
72
- rescue => e
73
- ctx.reply("Ruby Error: #{e.message}")
74
- end
75
- end
76
-
77
- bot.on(:callback_query) do |ctx|
78
- ctx.answer_callback_query(text: "Button clicked: #{ctx.data}")
79
-
80
- if ctx.data == 'test'
81
- ctx.edit_message_text("You clicked the test button!")
82
- end
83
- end
84
-
85
- if ENV['RACK_ENV'] == 'production'
86
- server = bot.webhook(port: ENV['PORT'] || 3000)
87
- server.run
88
- server.set_webhook
89
- else
90
- bot.start_polling(timeout: 30, limit: 100)
91
- end
data/public/index.html DELETED
@@ -1,481 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Telegem Docs - Telegram Bot Framework for Ruby</title>
7
- <style>
8
- * {
9
- margin: 0;
10
- padding: 0;
11
- box-sizing: border-box;
12
- }
13
-
14
- body {
15
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
16
- line-height: 1.6;
17
- color: #1a1a1a;
18
- background: #fafafa;
19
- padding: 0;
20
- }
21
-
22
- .container {
23
- max-width: 900px;
24
- margin: 0 auto;
25
- padding: 2rem 1.5rem;
26
- }
27
-
28
- .header {
29
- padding-bottom: 2rem;
30
- margin-bottom: 2rem;
31
- border-bottom: 1px solid #eaeaea;
32
- }
33
-
34
- .header h1 {
35
- font-size: 2.2rem;
36
- color: #2c3e50;
37
- margin-bottom: 0.25rem;
38
- }
39
-
40
- .tagline {
41
- font-size: 1.1rem;
42
- color: #7f8c8d;
43
- margin-bottom: 1.5rem;
44
- }
45
-
46
- .stats {
47
- display: flex;
48
- gap: 1.5rem;
49
- margin-top: 1rem;
50
- }
51
-
52
- .stat {
53
- background: white;
54
- padding: 0.75rem 1rem;
55
- border-radius: 6px;
56
- border: 1px solid #eaeaea;
57
- min-width: 120px;
58
- }
59
-
60
- .stat-label {
61
- font-size: 0.8rem;
62
- color: #95a5a6;
63
- text-transform: uppercase;
64
- letter-spacing: 0.5px;
65
- margin-bottom: 0.25rem;
66
- }
67
-
68
- .stat-value {
69
- font-size: 1.1rem;
70
- font-weight: 600;
71
- color: #2c3e50;
72
- }
73
-
74
- .doc-nav {
75
- display: flex;
76
- gap: 0.5rem;
77
- margin: 2rem 0;
78
- flex-wrap: wrap;
79
- }
80
-
81
- .nav-btn {
82
- background: white;
83
- border: 1px solid #ddd;
84
- padding: 0.5rem 1rem;
85
- border-radius: 4px;
86
- font-size: 0.9rem;
87
- color: #555;
88
- cursor: pointer;
89
- transition: all 0.2s;
90
- }
91
-
92
- .nav-btn:hover {
93
- border-color: #3498db;
94
- color: #3498db;
95
- }
96
-
97
- .nav-btn.active {
98
- background: #3498db;
99
- border-color: #3498db;
100
- color: white;
101
- }
102
-
103
- .doc-section {
104
- background: white;
105
- border-radius: 8px;
106
- padding: 2rem;
107
- margin-bottom: 1.5rem;
108
- border: 1px solid #eaeaea;
109
- }
110
-
111
- .doc-section h2 {
112
- font-size: 1.5rem;
113
- color: #2c3e50;
114
- margin-bottom: 1rem;
115
- padding-bottom: 0.5rem;
116
- border-bottom: 2px solid #f0f0f0;
117
- }
118
-
119
- .doc-section h3 {
120
- font-size: 1.1rem;
121
- color: #34495e;
122
- margin: 1.5rem 0 0.75rem;
123
- }
124
-
125
- .doc-section p {
126
- margin-bottom: 1rem;
127
- color: #555;
128
- }
129
-
130
- .method-list {
131
- list-style: none;
132
- margin: 1rem 0;
133
- }
134
-
135
- .method-item {
136
- margin-bottom: 0.75rem;
137
- padding: 0.75rem;
138
- background: #f8f9fa;
139
- border-radius: 4px;
140
- border-left: 3px solid #3498db;
141
- }
142
-
143
- .method-name {
144
- font-family: 'SF Mono', Monaco, Consolas, monospace;
145
- font-weight: 600;
146
- color: #2c3e50;
147
- margin-bottom: 0.25rem;
148
- }
149
-
150
- .method-desc {
151
- color: #7f8c8d;
152
- font-size: 0.9rem;
153
- }
154
-
155
- .code-block {
156
- background: #2c3e50;
157
- color: #ecf0f1;
158
- padding: 1.25rem;
159
- border-radius: 6px;
160
- margin: 1rem 0;
161
- font-family: 'SF Mono', Monaco, Consolas, monospace;
162
- font-size: 0.9rem;
163
- line-height: 1.5;
164
- overflow-x: auto;
165
- }
166
-
167
- .code-block::selection {
168
- background: #3498db;
169
- }
170
-
171
- .links {
172
- display: flex;
173
- gap: 1rem;
174
- margin-top: 2rem;
175
- padding-top: 1.5rem;
176
- border-top: 1px solid #eaeaea;
177
- flex-wrap: wrap;
178
- }
179
-
180
- .link-btn {
181
- display: inline-flex;
182
- align-items: center;
183
- gap: 0.5rem;
184
- padding: 0.6rem 1.2rem;
185
- background: #3498db;
186
- color: white;
187
- text-decoration: none;
188
- border-radius: 4px;
189
- font-size: 0.9rem;
190
- transition: background 0.2s;
191
- }
192
-
193
- .link-btn:hover {
194
- background: #2980b9;
195
- }
196
-
197
- .link-btn.secondary {
198
- background: white;
199
- color: #555;
200
- border: 1px solid #ddd;
201
- }
202
-
203
- .link-btn.secondary:hover {
204
- background: #f8f9fa;
205
- }
206
-
207
- .note {
208
- background: #f8f9fa;
209
- padding: 1rem;
210
- border-left: 3px solid #3498db;
211
- margin: 1rem 0;
212
- border-radius: 0 4px 4px 0;
213
- }
214
-
215
- @media (max-width: 768px) {
216
- .container {
217
- padding: 1rem;
218
- }
219
-
220
- .doc-section {
221
- padding: 1.5rem;
222
- }
223
-
224
- .stats {
225
- flex-direction: column;
226
- gap: 0.75rem;
227
- }
228
-
229
- .stat {
230
- min-width: auto;
231
- }
232
- }
233
- </style>
234
- </head>
235
- <body>
236
- <div class="container">
237
- <header class="header">
238
- <div>
239
- <h1>Telegem</h1>
240
- <p class="tagline">Telegram Bot Framework for Ruby</p>
241
- </div>
242
-
243
- <div class="stats">
244
- <div class="stat">
245
- <div class="stat-label">Version</div>
246
- <div class="stat-value" id="gem-version">Loading...</div>
247
- </div>
248
- <div class="stat">
249
- <div class="stat-label">Downloads</div>
250
- <div class="stat-value" id="gem-downloads">Loading...</div>
251
- </div>
252
- </div>
253
-
254
- <div class="doc-nav">
255
- <button class="nav-btn active" onclick="showDoc('quickstart')">Quick Start</button>
256
- <button class="nav-btn" onclick="showDoc('ctx')">Context API</button>
257
- <button class="nav-btn" onclick="showDoc('bot')">Bot API</button>
258
- <button class="nav-btn" onclick="showDoc('scenes')">Scenes</button>
259
- <button class="nav-btn" onclick="showDoc('webhook')">Webhook</button>
260
- </div>
261
- </header>
262
-
263
- <!-- Quick Start -->
264
- <section id="quickstart-doc" class="doc-section">
265
- <h2>Quick Start</h2>
266
-
267
- <h3>Installation</h3>
268
- <div class="code-block">
269
- # Add to Gemfile
270
- gem 'telegem'
271
-
272
- # Or install directly
273
- $ gem install telegem
274
- </div>
275
-
276
- <h3>Basic Usage</h3>
277
- <div class="code-block">
278
- require 'telegem'
279
-
280
- bot = Telegem.new("YOUR_BOT_TOKEN")
281
-
282
- bot.command('start') do |ctx|
283
- ctx.reply("Welcome to Telegem!")
284
- end
285
-
286
- bot.command('help') do |ctx|
287
- ctx.reply("Available commands: /start, /help")
288
- end
289
-
290
- # Start the bot
291
- bot.start_polling
292
- </div>
293
-
294
- <div class="note">
295
- Replace <code>YOUR_BOT_TOKEN</code> with your actual Telegram Bot token from @BotFather
296
- </div>
297
-
298
- <div class="links">
299
- <a href="https://rubygems.org/gems/telegem" class="link-btn">📦 View on RubyGems</a>
300
- <a href="https://gitlab.com/ruby-telegem/telegem" class="link-btn secondary">🐱 GitLab Repository</a>
301
- </div>
302
- </section>
303
-
304
- <!-- ctx API -->
305
- <section id="ctx-doc" class="doc-section" style="display: none;">
306
- <h2>Context API</h2>
307
- <p>The context object provides access to the current update and response methods.</p>
308
-
309
- <h3>Properties</h3>
310
- <ul class="method-list">
311
- <li class="method-item">
312
- <div class="method-name">ctx.message</div>
313
- <div class="method-desc">Current message object</div>
314
- </li>
315
- <li class="method-item">
316
- <div class="method-name">ctx.from</div>
317
- <div class="method-desc">User who sent the message</div>
318
- </li>
319
- <li class="method-item">
320
- <div class="method-name">ctx.chat</div>
321
- <div class="method-desc">Chat information</div>
322
- </li>
323
- <li class="method-item">
324
- <div class="method-name">ctx.session</div>
325
- <div class="method-desc">Persistent user storage</div>
326
- </li>
327
- </ul>
328
-
329
- <h3>Methods</h3>
330
- <div class="code-block">
331
- # Send message
332
- ctx.reply("Hello!")
333
-
334
- # Send photo
335
- ctx.photo("photo.jpg", caption: "My photo")
336
-
337
- # Edit message
338
- ctx.edit_message_text("Updated text")
339
-
340
- # Delete message
341
- ctx.delete_message(message_id)
342
- </div>
343
-
344
- <div class="links">
345
- <a href="https://gitlab.com/ruby-telegem/telegem/-/tree/main/docs/context.md" class="link-btn">📄 Full Context Docs</a>
346
- </div>
347
- </section>
348
-
349
- <!-- Bot API -->
350
- <section id="bot-doc" class="doc-section" style="display: none;">
351
- <h2>Bot API</h2>
352
- <p>Configure handlers and control bot lifecycle.</p>
353
-
354
- <div class="code-block">
355
- # Handle commands
356
- bot.command('start') { |ctx| ctx.reply("Welcome") }
357
-
358
- # Handle text patterns
359
- bot.hears(/hello/i) { |ctx| ctx.reply("Hi there!") }
360
-
361
- # Handle specific update types
362
- bot.on(:photo) { |ctx| ctx.reply("Nice photo!") }
363
- bot.on(:callback_query) { |ctx| ctx.answer_callback_query }
364
-
365
- # Start bot
366
- bot.start_polling
367
- # or
368
- bot.webhook.run
369
- </div>
370
-
371
- <div class="links">
372
- <a href="https://gitlab.com/ruby-telegem/telegem/-/tree/main/docs/bot.md" class="link-btn">📄 Bot API Reference</a>
373
- </div>
374
- </section>
375
-
376
- <!-- Scenes -->
377
- <section id="scenes-doc" class="doc-section" style="display: none;">
378
- <h2>Scenes</h2>
379
- <p>Multi-step conversations for complex interactions.</p>
380
-
381
- <div class="code-block">
382
- bot.scene :registration do
383
- step :ask_name do |ctx|
384
- ctx.reply("What is your name?")
385
- end
386
-
387
- step :save_name do |ctx|
388
- ctx.session[:name] = ctx.message.text
389
- ctx.reply("Hello #{ctx.session[:name]}!")
390
- ctx.leave_scene
391
- end
392
- end
393
-
394
- # Enter scene
395
- bot.command('register') { |ctx| ctx.enter_scene(:registration) }
396
- </div>
397
-
398
- <div class="links">
399
- <a href="https://gitlab.com/ruby-telegem/telegem/-/tree/main/docs/scenes.md" class="link-btn">📄 Scenes Guide</a>
400
- </div>
401
- </section>
402
-
403
- <!-- Webhook -->
404
- <section id="webhook-doc" class="doc-section" style="display: none;">
405
- <h2>Webhook Deployment</h2>
406
- <p>Production deployment with webhooks.</p>
407
-
408
- <div class="code-block">
409
- # Production setup
410
- bot = Telegem.new("TOKEN")
411
-
412
- # Configure webhook
413
- bot.webhook(
414
- url: 'https://your-domain.com/webhook',
415
- port: 3000
416
- ).run
417
-
418
- # For cloud platforms
419
- bot.webhook.run # Auto-detects platform
420
- </div>
421
-
422
- <div class="note">
423
- Webhook mode is recommended for production. Uses less resources than polling.
424
- </div>
425
-
426
- <div class="links">
427
- <a href="https://gitlab.com/ruby-telegem/telegem/-/tree/main/docs/deployment.md" class="link-btn">📄 Deployment Guide</a>
428
- </div>
429
- </section>
430
-
431
- <!-- Footer -->
432
- <div class="doc-section">
433
- <div class="links">
434
- <a href="https://gitlab.com/ruby-telegem/telegem" class="link-btn">🏠 Main Repository</a>
435
- <a href="https://rubygems.org/gems/telegem" class="link-btn secondary">💎 RubyGems</a>
436
- <a href="https://gitlab.com/ruby-telegem/telegem/-/issues" class="link-btn secondary">🐛 Issue Tracker</a>
437
- </div>
438
- </div>
439
- </div>
440
-
441
- <script>
442
- async function fetchGemStats() {
443
- try {
444
- const response = await fetch('https://rubygems.org/api/v1/gems/telegem.json');
445
- const data = await response.json();
446
-
447
- if (data.version) {
448
- document.getElementById('gem-version').textContent = `v${data.version}`;
449
- }
450
-
451
- if (data.downloads) {
452
- document.getElementById('gem-downloads').textContent =
453
- data.downloads.toLocaleString();
454
- }
455
- } catch (error) {
456
- document.getElementById('gem-version').textContent = 'v3.0.0';
457
- document.getElementById('gem-downloads').textContent = 'N/A';
458
- }
459
- }
460
-
461
- function showDoc(section) {
462
- document.querySelectorAll('.doc-section').forEach(el => {
463
- el.style.display = 'none';
464
- });
465
-
466
- document.getElementById(`${section}-doc`).style.display = 'block';
467
-
468
- document.querySelectorAll('.nav-btn').forEach(btn => {
469
- btn.classList.remove('active');
470
- });
471
- event.target.classList.add('active');
472
-
473
- window.scrollTo(0, 0);
474
- }
475
-
476
- document.addEventListener('DOMContentLoaded', () => {
477
- fetchGemStats();
478
- });
479
- </script>
480
- </body>
481
- </html>