telegem 1.0.6 → 2.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/docs/Api.md +146 -354
- data/docs/Cookbook(copy_paste).md +644 -0
- data/docs/Getting_started.md +348 -0
- data/docs/webhook_setup.md +199 -0
- data/lib/api/client.rb +123 -49
- data/lib/api/types.rb +283 -67
- data/lib/core/bot.rb +91 -56
- data/lib/core/context.rb +96 -110
- data/lib/markup/.gitkeep +0 -0
- data/lib/markup/keyboard.rb +53 -38
- data/lib/telegem.rb +15 -5
- data/lib/webhook/server.rb +246 -112
- metadata +108 -17
- data/docs/Cookbook.md +0 -407
- data/docs/SETTING_WEBHOOK.md +0 -367
- data/docs/UNDERSTANDING-WEBHOOK-n-POLLING.md +0 -241
data/lib/webhook/server.rb
CHANGED
|
@@ -1,132 +1,196 @@
|
|
|
1
|
-
# lib/webhook/server.rb -
|
|
1
|
+
# lib/webhook/server.rb - V2.0.0 (CLOUD-READY)
|
|
2
2
|
require 'json'
|
|
3
|
-
require '
|
|
3
|
+
require 'rack'
|
|
4
4
|
|
|
5
5
|
module Telegem
|
|
6
6
|
module Webhook
|
|
7
7
|
class Server
|
|
8
|
-
attr_reader :bot, :port, :host, :logger, :
|
|
9
|
-
|
|
10
|
-
def initialize(bot, port: nil, host: '0.0.0.0', logger: nil)
|
|
8
|
+
attr_reader :bot, :port, :host, :logger, :running, :secret_token
|
|
9
|
+
|
|
10
|
+
def initialize(bot, port: nil, host: '0.0.0.0', logger: nil, max_threads: 10, secret_token: nil)
|
|
11
11
|
@bot = bot
|
|
12
|
-
@port = port || ENV['PORT'] ||
|
|
12
|
+
@port = port || ENV['PORT'] || 3000
|
|
13
13
|
@host = host
|
|
14
14
|
@logger = logger || Logger.new($stdout)
|
|
15
|
+
@max_threads = max_threads
|
|
16
|
+
@thread_pool = Concurrent::FixedThreadPool.new(max_threads)
|
|
17
|
+
@secret_token = secret_token || generate_secret_token
|
|
15
18
|
@server = nil
|
|
16
19
|
@running = false
|
|
20
|
+
@webhook_path = "/webhook"
|
|
17
21
|
end
|
|
18
|
-
|
|
22
|
+
|
|
23
|
+
# Production server with Puma
|
|
19
24
|
def run
|
|
20
25
|
return if @running
|
|
21
26
|
|
|
22
27
|
@logger.info "🚀 Starting Telegem webhook server on #{@host}:#{@port}"
|
|
23
|
-
@logger.info "📝 Set
|
|
28
|
+
@logger.info "📝 Set Telegram webhook to: #{webhook_url}"
|
|
29
|
+
@logger.info "🔐 Secret token: #{@secret_token}"
|
|
30
|
+
@logger.info "✅ Using Puma (production-ready)"
|
|
31
|
+
@logger.info "☁️ Cloud-ready: #{cloud_platform}"
|
|
24
32
|
|
|
25
33
|
@running = true
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# Create WEBrick server
|
|
30
|
-
@server = WEBrick::HTTPServer.new(
|
|
31
|
-
Port: @port,
|
|
32
|
-
BindAddress: @host,
|
|
33
|
-
Logger: @logger,
|
|
34
|
-
AccessLog: []
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
# Mount the webhook endpoint
|
|
38
|
-
@server.mount_proc("/webhook/#{@bot.token}") do |req, res|
|
|
39
|
-
handle_webhook_request(req, res)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Mount health check
|
|
43
|
-
@server.mount_proc('/health') do |req, res|
|
|
44
|
-
res.status = 200
|
|
45
|
-
res.content_type = 'text/plain'
|
|
46
|
-
res.body = 'OK'
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# Mount root
|
|
50
|
-
@server.mount_proc('/') do |req, res|
|
|
51
|
-
res.status = 200
|
|
52
|
-
res.content_type = 'text/html'
|
|
53
|
-
res.body = <<~HTML
|
|
54
|
-
<html>
|
|
55
|
-
<head><title>Telegem Webhook Server</title></head>
|
|
56
|
-
<body>
|
|
57
|
-
<h1>Telegem Webhook Server</h1>
|
|
58
|
-
<p>Webhook URL: <code>#{webhook_url}</code></p>
|
|
59
|
-
<p>Status: <span style="color: green;">Running</span></p>
|
|
60
|
-
<p><a href="/health">Health Check</a></p>
|
|
61
|
-
</body>
|
|
62
|
-
</html>
|
|
63
|
-
HTML
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Handle shutdown signals
|
|
67
|
-
['INT', 'TERM'].each do |signal|
|
|
68
|
-
Signal.trap(signal) { shutdown }
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Start the server
|
|
72
|
-
@server.start
|
|
73
|
-
|
|
74
|
-
rescue => e
|
|
75
|
-
@logger.error "❌ Webhook server error: #{e.class}: #{e.message}"
|
|
76
|
-
@logger.error e.backtrace.join("\n") if e.backtrace
|
|
77
|
-
raise
|
|
78
|
-
ensure
|
|
79
|
-
@running = false
|
|
80
|
-
end
|
|
81
|
-
end
|
|
35
|
+
app = build_rack_app
|
|
36
|
+
start_puma_server(app)
|
|
82
37
|
|
|
83
38
|
self
|
|
84
39
|
end
|
|
85
|
-
|
|
40
|
+
|
|
86
41
|
def stop
|
|
87
42
|
return unless @running
|
|
88
43
|
|
|
89
44
|
@logger.info "🛑 Stopping webhook server..."
|
|
90
45
|
@running = false
|
|
91
46
|
|
|
92
|
-
|
|
93
|
-
@
|
|
94
|
-
|
|
95
|
-
# Wait for server thread
|
|
96
|
-
@server_thread&.join(5)
|
|
47
|
+
@server&.stop
|
|
48
|
+
@thread_pool.shutdown
|
|
49
|
+
@thread_pool.wait_for_termination(5)
|
|
97
50
|
|
|
98
51
|
@logger.info "✅ Webhook server stopped"
|
|
99
52
|
end
|
|
100
|
-
|
|
53
|
+
|
|
101
54
|
alias_method :shutdown, :stop
|
|
102
|
-
|
|
55
|
+
|
|
103
56
|
def running?
|
|
104
57
|
@running
|
|
105
58
|
end
|
|
106
|
-
|
|
59
|
+
|
|
107
60
|
def webhook_url
|
|
108
|
-
|
|
109
|
-
|
|
61
|
+
# For cloud platforms, use their URL
|
|
62
|
+
if cloud_url = detect_cloud_url
|
|
63
|
+
"#{cloud_url}#{@webhook_path}"
|
|
64
|
+
elsif ENV['WEBHOOK_URL']
|
|
65
|
+
ENV['WEBHOOK_URL']
|
|
66
|
+
else
|
|
67
|
+
# Local development
|
|
68
|
+
"https://#{@host}:#{@port}#{@webhook_path}"
|
|
69
|
+
end
|
|
110
70
|
end
|
|
111
|
-
|
|
71
|
+
|
|
72
|
+
def set_webhook(**options)
|
|
73
|
+
params = {
|
|
74
|
+
url: webhook_url,
|
|
75
|
+
secret_token: @secret_token,
|
|
76
|
+
drop_pending_updates: true
|
|
77
|
+
}.merge(options)
|
|
78
|
+
|
|
79
|
+
@bot.api.call!('setWebhook', params)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def delete_webhook
|
|
83
|
+
@bot.api.call!('deleteWebhook', {})
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Quick setup helper
|
|
87
|
+
def self.setup(bot, **options)
|
|
88
|
+
server = new(bot, **options)
|
|
89
|
+
server.run
|
|
90
|
+
server.set_webhook
|
|
91
|
+
server
|
|
92
|
+
end
|
|
93
|
+
|
|
112
94
|
private
|
|
113
|
-
|
|
114
|
-
def
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
95
|
+
|
|
96
|
+
def build_rack_app
|
|
97
|
+
Rack::Builder.new do
|
|
98
|
+
use Rack::CommonLogger
|
|
99
|
+
use Rack::ShowExceptions if ENV['RACK_ENV'] == 'development'
|
|
100
|
+
|
|
101
|
+
# Health endpoint (required by Render/Railway/Heroku)
|
|
102
|
+
map "/health" do
|
|
103
|
+
run ->(env) {
|
|
104
|
+
[200, {
|
|
105
|
+
'Content-Type' => 'application/json',
|
|
106
|
+
'Cache-Control' => 'no-cache'
|
|
107
|
+
}, [{
|
|
108
|
+
status: 'healthy',
|
|
109
|
+
timestamp: Time.now.iso8601,
|
|
110
|
+
service: 'telegem-webhook',
|
|
111
|
+
version: Telegem::VERSION
|
|
112
|
+
}.to_json]]
|
|
113
|
+
}
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Webhook endpoint
|
|
117
|
+
map "/webhook" do
|
|
118
|
+
run ->(env) do
|
|
119
|
+
server = env['telegem.server']
|
|
120
|
+
req = Rack::Request.new(env)
|
|
121
|
+
|
|
122
|
+
if req.post?
|
|
123
|
+
server.handle_rack_request(req)
|
|
124
|
+
else
|
|
125
|
+
[405, { 'Content-Type' => 'text/plain' }, ['Method Not Allowed']]
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Root landing page
|
|
131
|
+
map "/" do
|
|
132
|
+
run ->(env) do
|
|
133
|
+
server = env['telegem.server']
|
|
134
|
+
[200, { 'Content-Type' => 'text/html' }, [server.landing_page]]
|
|
135
|
+
end
|
|
136
|
+
end
|
|
121
137
|
end
|
|
122
|
-
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def start_puma_server(app)
|
|
141
|
+
require 'puma'
|
|
142
|
+
|
|
143
|
+
# Cloud platforms set PORT environment variable
|
|
144
|
+
port = ENV['PORT'] || @port
|
|
145
|
+
|
|
146
|
+
config = {
|
|
147
|
+
Host: @host,
|
|
148
|
+
Port: port,
|
|
149
|
+
Threads: "0:#{@max_threads}",
|
|
150
|
+
workers: ENV['WEB_CONCURRENCY']&.to_i || 1,
|
|
151
|
+
daemonize: false,
|
|
152
|
+
silent: false,
|
|
153
|
+
environment: ENV['RACK_ENV'] || 'production',
|
|
154
|
+
# Cloud platforms handle SSL termination
|
|
155
|
+
ssl_bind: nil # Let platform handle SSL
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@server = Puma::Server.new(app)
|
|
159
|
+
@server.add_tcp_listener(@host, port)
|
|
160
|
+
|
|
161
|
+
@server.app = ->(env) do
|
|
162
|
+
env['telegem.server'] = self
|
|
163
|
+
app.call(env)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
Thread.new do
|
|
167
|
+
begin
|
|
168
|
+
@server.run
|
|
169
|
+
rescue => e
|
|
170
|
+
@logger.error "❌ Puma server error: #{e.message}"
|
|
171
|
+
@running = false
|
|
172
|
+
raise
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
sleep 1 until @server.running?
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def handle_rack_request(req)
|
|
180
|
+
# Validate secret token from Telegram
|
|
181
|
+
telegram_token = req.get_header('X-Telegram-Bot-Api-Secret-Token')
|
|
182
|
+
|
|
183
|
+
if @secret_token && telegram_token != @secret_token
|
|
184
|
+
@logger.warn "⚠️ Invalid secret token from #{req.ip}"
|
|
185
|
+
return [403, { 'Content-Type' => 'text/plain' }, ['Forbidden']]
|
|
186
|
+
end
|
|
187
|
+
|
|
123
188
|
begin
|
|
124
|
-
# Parse the update
|
|
125
189
|
body = req.body.read
|
|
126
190
|
update_data = JSON.parse(body)
|
|
127
191
|
|
|
128
|
-
# Process
|
|
129
|
-
|
|
192
|
+
# Process in thread pool (not spawn new threads!)
|
|
193
|
+
@thread_pool.post do
|
|
130
194
|
begin
|
|
131
195
|
@bot.process(update_data)
|
|
132
196
|
rescue => e
|
|
@@ -134,57 +198,127 @@ module Telegem
|
|
|
134
198
|
end
|
|
135
199
|
end
|
|
136
200
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
res.body = 'OK'
|
|
141
|
-
|
|
142
|
-
rescue JSON::ParserError => e
|
|
143
|
-
@logger.error "Invalid JSON in webhook request: #{e.message}"
|
|
144
|
-
res.status = 400
|
|
145
|
-
res.content_type = 'text/plain'
|
|
146
|
-
res.body = 'Bad Request'
|
|
201
|
+
[200, { 'Content-Type' => 'text/plain' }, ['OK']]
|
|
202
|
+
rescue JSON::ParserError
|
|
203
|
+
[400, { 'Content-Type' => 'text/plain' }, ['Bad Request']]
|
|
147
204
|
rescue => e
|
|
148
|
-
@logger.error "
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
205
|
+
@logger.error "Webhook error: #{e.message}"
|
|
206
|
+
[500, { 'Content-Type' => 'text/plain' }, ['Internal Server Error']]
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def landing_page
|
|
211
|
+
<<~HTML
|
|
212
|
+
<!DOCTYPE html>
|
|
213
|
+
<html>
|
|
214
|
+
<head>
|
|
215
|
+
<title>Telegem Webhook Server</title>
|
|
216
|
+
<style>
|
|
217
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
218
|
+
max-width: 800px; margin: 0 auto; padding: 20px; }
|
|
219
|
+
.status { background: #4CAF50; color: white; padding: 5px 10px; border-radius: 3px; }
|
|
220
|
+
code { background: #f5f5f5; padding: 2px 5px; border-radius: 3px; }
|
|
221
|
+
a { color: #2196F3; text-decoration: none; }
|
|
222
|
+
</style>
|
|
223
|
+
</head>
|
|
224
|
+
<body>
|
|
225
|
+
<h1>🤖 Telegem Webhook Server</h1>
|
|
226
|
+
<p><strong>Status:</strong> <span class="status">Running</span></p>
|
|
227
|
+
<p><strong>Webhook URL:</strong> <code>#{webhook_url}</code></p>
|
|
228
|
+
<p><strong>Health Check:</strong> <a href="/health">/health</a></p>
|
|
229
|
+
<p><strong>Platform:</strong> #{cloud_platform}</p>
|
|
230
|
+
<hr>
|
|
231
|
+
<p>To set up your Telegram bot:</p>
|
|
232
|
+
<pre><code>bot = Telegem.new('YOUR_TOKEN')
|
|
233
|
+
server = bot.webhook
|
|
234
|
+
server.run
|
|
235
|
+
server.set_webhook</code></pre>
|
|
236
|
+
</body>
|
|
237
|
+
</html>
|
|
238
|
+
HTML
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def generate_secret_token
|
|
242
|
+
SecureRandom.hex(32)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def detect_cloud_url
|
|
246
|
+
# Render
|
|
247
|
+
if ENV['RENDER_EXTERNAL_URL']
|
|
248
|
+
ENV['RENDER_EXTERNAL_URL']
|
|
249
|
+
# Railway
|
|
250
|
+
elsif ENV['RAILWAY_STATIC_URL']
|
|
251
|
+
ENV['RAILWAY_STATIC_URL']
|
|
252
|
+
# Heroku
|
|
253
|
+
elsif ENV['HEROKU_APP_NAME']
|
|
254
|
+
"https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com"
|
|
255
|
+
# Fly.io
|
|
256
|
+
elsif ENV['FLY_APP_NAME']
|
|
257
|
+
"https://#{ENV['FLY_APP_NAME']}.fly.dev"
|
|
258
|
+
# Vercel (if using serverless)
|
|
259
|
+
elsif ENV['VERCEL_URL']
|
|
260
|
+
"https://#{ENV['VERCEL_URL']}"
|
|
261
|
+
else
|
|
262
|
+
nil
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def cloud_platform
|
|
267
|
+
if ENV['RENDER'] then 'Render'
|
|
268
|
+
elsif ENV['RAILWAY'] then 'Railway'
|
|
269
|
+
elsif ENV['HEROKU_APP_NAME'] then 'Heroku'
|
|
270
|
+
elsif ENV['FLY_APP_NAME'] then 'Fly.io'
|
|
271
|
+
elsif ENV['VERCEL'] then 'Vercel'
|
|
272
|
+
elsif ENV['DYNO'] then 'Heroku'
|
|
273
|
+
else 'Local/Unknown'
|
|
152
274
|
end
|
|
153
275
|
end
|
|
154
276
|
end
|
|
155
|
-
|
|
156
|
-
# Middleware for
|
|
277
|
+
|
|
278
|
+
# Rack Middleware for existing apps
|
|
157
279
|
class Middleware
|
|
158
|
-
def initialize(app, bot)
|
|
280
|
+
def initialize(app, bot, secret_token: nil)
|
|
159
281
|
@app = app
|
|
160
282
|
@bot = bot
|
|
283
|
+
@secret_token = secret_token || ENV['TELEGRAM_SECRET_TOKEN']
|
|
284
|
+
@thread_pool = Concurrent::FixedThreadPool.new(10)
|
|
161
285
|
end
|
|
162
|
-
|
|
286
|
+
|
|
163
287
|
def call(env)
|
|
164
288
|
req = Rack::Request.new(env)
|
|
165
289
|
|
|
166
|
-
|
|
167
|
-
if req.post? && req.path == "/webhook/#{@bot.token}"
|
|
290
|
+
if req.post? && req.path == "/webhook"
|
|
168
291
|
handle_webhook(req)
|
|
169
292
|
else
|
|
170
293
|
@app.call(env)
|
|
171
294
|
end
|
|
172
295
|
end
|
|
173
|
-
|
|
296
|
+
|
|
174
297
|
private
|
|
175
|
-
|
|
298
|
+
|
|
176
299
|
def handle_webhook(req)
|
|
300
|
+
telegram_token = req.get_header('X-Telegram-Bot-Api-Secret-Token')
|
|
301
|
+
|
|
302
|
+
if @secret_token && telegram_token != @secret_token
|
|
303
|
+
return [403, { 'Content-Type' => 'text/plain' }, ['Forbidden']]
|
|
304
|
+
end
|
|
305
|
+
|
|
177
306
|
begin
|
|
178
307
|
update_data = JSON.parse(req.body.read)
|
|
179
308
|
|
|
180
|
-
|
|
181
|
-
|
|
309
|
+
@thread_pool.post do
|
|
310
|
+
begin
|
|
311
|
+
@bot.process(update_data)
|
|
312
|
+
rescue => e
|
|
313
|
+
@bot.logger&.error("Webhook error: #{e.message}")
|
|
314
|
+
end
|
|
315
|
+
end
|
|
182
316
|
|
|
183
317
|
[200, { 'Content-Type' => 'text/plain' }, ['OK']]
|
|
184
318
|
rescue JSON::ParserError
|
|
185
319
|
[400, { 'Content-Type' => 'text/plain' }, ['Bad Request']]
|
|
186
320
|
rescue => e
|
|
187
|
-
@bot.logger
|
|
321
|
+
@bot.logger&.error("Webhook error: #{e.message}")
|
|
188
322
|
[500, { 'Content-Type' => 'text/plain' }, ['Internal Server Error']]
|
|
189
323
|
end
|
|
190
324
|
end
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: telegem
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- sick_phantom
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
@@ -15,14 +15,68 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: '0.20'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: '0.20'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: concurrent-ruby
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.2'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.2'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rack
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2.0'
|
|
47
|
+
- - "<"
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '4.0'
|
|
50
|
+
type: :runtime
|
|
51
|
+
prerelease: false
|
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '2.0'
|
|
57
|
+
- - "<"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '4.0'
|
|
60
|
+
- !ruby/object:Gem::Dependency
|
|
61
|
+
name: puma
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '5.0'
|
|
67
|
+
- - "<"
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '7.0'
|
|
70
|
+
type: :runtime
|
|
71
|
+
prerelease: false
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '5.0'
|
|
77
|
+
- - "<"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '7.0'
|
|
26
80
|
- !ruby/object:Gem::Dependency
|
|
27
81
|
name: rake
|
|
28
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -43,32 +97,62 @@ dependencies:
|
|
|
43
97
|
requirements:
|
|
44
98
|
- - "~>"
|
|
45
99
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '3.
|
|
100
|
+
version: '3.12'
|
|
101
|
+
type: :development
|
|
102
|
+
prerelease: false
|
|
103
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - "~>"
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: '3.12'
|
|
108
|
+
- !ruby/object:Gem::Dependency
|
|
109
|
+
name: simplecov
|
|
110
|
+
requirement: !ruby/object:Gem::Requirement
|
|
111
|
+
requirements:
|
|
112
|
+
- - "~>"
|
|
113
|
+
- !ruby/object:Gem::Version
|
|
114
|
+
version: '0.22'
|
|
115
|
+
type: :development
|
|
116
|
+
prerelease: false
|
|
117
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
118
|
+
requirements:
|
|
119
|
+
- - "~>"
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: '0.22'
|
|
122
|
+
- !ruby/object:Gem::Dependency
|
|
123
|
+
name: webmock
|
|
124
|
+
requirement: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - "~>"
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: '3.18'
|
|
47
129
|
type: :development
|
|
48
130
|
prerelease: false
|
|
49
131
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
132
|
requirements:
|
|
51
133
|
- - "~>"
|
|
52
134
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '3.
|
|
135
|
+
version: '3.18'
|
|
54
136
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name:
|
|
137
|
+
name: rubocop
|
|
56
138
|
requirement: !ruby/object:Gem::Requirement
|
|
57
139
|
requirements:
|
|
58
140
|
- - "~>"
|
|
59
141
|
- !ruby/object:Gem::Version
|
|
60
|
-
version:
|
|
142
|
+
version: '1.50'
|
|
61
143
|
type: :development
|
|
62
144
|
prerelease: false
|
|
63
145
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
146
|
requirements:
|
|
65
147
|
- - "~>"
|
|
66
148
|
- !ruby/object:Gem::Version
|
|
67
|
-
version:
|
|
68
|
-
description:
|
|
69
|
-
by Telegraf.js
|
|
149
|
+
version: '1.50'
|
|
150
|
+
description: |
|
|
151
|
+
Telegem is a modern Telegram Bot Framework for Ruby inspired by Telegraf.js.
|
|
152
|
+
Built with async-first design using HTTPX, featuring scenes, middleware,
|
|
153
|
+
and a clean DSL. Perfect for building scalable Telegram bots.
|
|
70
154
|
email:
|
|
71
|
-
-
|
|
155
|
+
- ynwghosted@icloud.com
|
|
72
156
|
executables: []
|
|
73
157
|
extensions: []
|
|
74
158
|
extra_rdoc_files: []
|
|
@@ -84,19 +168,20 @@ files:
|
|
|
84
168
|
- Test-Projects/pizza_test_bot_guide.md
|
|
85
169
|
- docs/.gitkeep
|
|
86
170
|
- docs/Api.md
|
|
87
|
-
- docs/Cookbook.md
|
|
171
|
+
- docs/Cookbook(copy_paste).md
|
|
172
|
+
- docs/Getting_started.md
|
|
88
173
|
- docs/How_to_use.md
|
|
89
174
|
- docs/QuickStart.md
|
|
90
|
-
- docs/SETTING_WEBHOOK.md
|
|
91
|
-
- docs/UNDERSTANDING-WEBHOOK-n-POLLING.md
|
|
92
175
|
- docs/Understanding_Scene.md
|
|
93
176
|
- docs/Usage.md
|
|
177
|
+
- docs/webhook_setup.md
|
|
94
178
|
- lib/api/client.rb
|
|
95
179
|
- lib/api/types.rb
|
|
96
180
|
- lib/core/bot.rb
|
|
97
181
|
- lib/core/composer.rb
|
|
98
182
|
- lib/core/context.rb
|
|
99
183
|
- lib/core/scene.rb
|
|
184
|
+
- lib/markup/.gitkeep
|
|
100
185
|
- lib/markup/keyboard.rb
|
|
101
186
|
- lib/session/memory_store.rb
|
|
102
187
|
- lib/session/middleware.rb
|
|
@@ -110,7 +195,13 @@ metadata:
|
|
|
110
195
|
homepage_uri: https://gitlab.com/ruby-telegem/telegem
|
|
111
196
|
source_code_uri: https://gitlab.com/ruby-telegem/telegem
|
|
112
197
|
changelog_uri: https://gitlab.com/ruby-telegem/telegem/-/blob/main/CHANGELOG.md
|
|
113
|
-
|
|
198
|
+
bug_tracker_uri: https://gitlab.com/ruby-telegem/telegem/-/issues
|
|
199
|
+
documentation_uri: https://gitlab.com/ruby-telegem/telegem/-/blob/main/README.md
|
|
200
|
+
rubygems_mfa_required: 'false'
|
|
201
|
+
post_install_message: "Thanks for installing Telegem 2.0.0!\n\nQuick start:\n bot
|
|
202
|
+
= Telegem.new(\"YOUR_TOKEN\")\n bot.on(:message) { |ctx| ctx.reply(\"Hello!\")
|
|
203
|
+
}\n bot.start_polling\n\nDocumentation: https://gitlab.com/ruby-telegem/telegem\nHappy
|
|
204
|
+
bot building! \U0001F916\n"
|
|
114
205
|
rdoc_options: []
|
|
115
206
|
require_paths:
|
|
116
207
|
- lib
|
|
@@ -127,5 +218,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
127
218
|
requirements: []
|
|
128
219
|
rubygems_version: 3.6.9
|
|
129
220
|
specification_version: 4
|
|
130
|
-
summary: Modern,
|
|
221
|
+
summary: Modern, fast Telegram Bot Framework for Ruby
|
|
131
222
|
test_files: []
|