telegem 3.5.0 → 3.6.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/.anv +2 -0
- data/README.md +1 -0
- data/_config.yml +10 -0
- data/docs/changelog.md +134 -169
- data/docs/webhooks.md +511 -19
- data/lib/api/client.rb +176 -55
- data/lib/api/types.rb +1 -4
- data/lib/core/context.rb +56 -0
- data/lib/telegem.rb +1 -1
- data/lib/webhook/server.rb +36 -14
- metadata +22 -8
- data/CODE_OF_CONDUCT.md +0 -13
- data/Gemfile.lock +0 -11
data/lib/api/client.rb
CHANGED
|
@@ -1,11 +1,112 @@
|
|
|
1
|
-
require
|
|
2
|
-
require
|
|
1
|
+
require "async/http"
|
|
2
|
+
require "json"
|
|
3
|
+
require "logger"
|
|
4
|
+
require "securerandom"
|
|
5
|
+
require "stringio"
|
|
6
|
+
require "tempfile"
|
|
3
7
|
|
|
4
8
|
module Telegem
|
|
5
9
|
module API
|
|
10
|
+
class MultipartForm
|
|
11
|
+
CRLF = "\r\n"
|
|
12
|
+
|
|
13
|
+
attr_reader :content_type
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@boundary = "----telegem#{SecureRandom.hex(16)}"
|
|
17
|
+
@content_type = "multipart/form-data; boundary=#{@boundary}"
|
|
18
|
+
@parts = []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add(name, value)
|
|
22
|
+
if file?(value)
|
|
23
|
+
append_file(name, value)
|
|
24
|
+
else
|
|
25
|
+
append_field(name, value.to_s)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def body
|
|
30
|
+
String.new.tap do |buffer|
|
|
31
|
+
@parts.each do |part|
|
|
32
|
+
buffer << "--#{@boundary}#{CRLF}"
|
|
33
|
+
buffer << part
|
|
34
|
+
buffer << CRLF
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
buffer << "--#{@boundary}--#{CRLF}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def append_field(name, value)
|
|
44
|
+
@parts << <<~PART.gsub("\n", CRLF)
|
|
45
|
+
Content-Disposition: form-data; name="#{name}"
|
|
46
|
+
|
|
47
|
+
#{value}
|
|
48
|
+
PART
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def append_file(name, value)
|
|
52
|
+
io =
|
|
53
|
+
case value
|
|
54
|
+
when String
|
|
55
|
+
File.open(value, "rb")
|
|
56
|
+
else
|
|
57
|
+
value
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
filename =
|
|
61
|
+
if io.respond_to?(:path) && io.path
|
|
62
|
+
File.basename(io.path)
|
|
63
|
+
else
|
|
64
|
+
"upload.bin"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
mime =
|
|
68
|
+
case File.extname(filename).downcase
|
|
69
|
+
when ".jpg", ".jpeg"
|
|
70
|
+
"image/jpeg"
|
|
71
|
+
when ".png"
|
|
72
|
+
"image/png"
|
|
73
|
+
when ".gif"
|
|
74
|
+
"image/gif"
|
|
75
|
+
when ".webp"
|
|
76
|
+
"image/webp"
|
|
77
|
+
when ".mp4"
|
|
78
|
+
"video/mp4"
|
|
79
|
+
when ".mp3"
|
|
80
|
+
"audio/mpeg"
|
|
81
|
+
when ".ogg"
|
|
82
|
+
"audio/ogg"
|
|
83
|
+
when ".pdf"
|
|
84
|
+
"application/pdf"
|
|
85
|
+
else
|
|
86
|
+
"application/octet-stream"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
@parts << String.new.tap do |part|
|
|
90
|
+
part << %(Content-Disposition: form-data; name="#{name}"; filename="#{filename}") << CRLF
|
|
91
|
+
part << "Content-Type: #{mime}" << CRLF
|
|
92
|
+
part << CRLF
|
|
93
|
+
part << io.read
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
io.close if value.is_a?(String)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def file?(obj)
|
|
100
|
+
obj.is_a?(File) ||
|
|
101
|
+
obj.is_a?(Tempfile) ||
|
|
102
|
+
obj.is_a?(StringIO) ||
|
|
103
|
+
(obj.is_a?(String) && File.file?(obj))
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
6
107
|
class Client
|
|
7
|
-
BASE_URL =
|
|
8
|
-
|
|
108
|
+
BASE_URL = "https://api.telegram.org"
|
|
109
|
+
|
|
9
110
|
attr_reader :token, :logger
|
|
10
111
|
|
|
11
112
|
def initialize(token, **options)
|
|
@@ -13,20 +114,21 @@ module Telegem
|
|
|
13
114
|
@logger = options[:logger] || Logger.new($stdout)
|
|
14
115
|
@timeout = options[:timeout] || 30
|
|
15
116
|
@retries = options[:retries] || 3
|
|
16
|
-
@retry_delay = options[:retry_delay] || 1
|
|
17
|
-
|
|
117
|
+
@retry_delay = options[:retry_delay] || 1
|
|
118
|
+
|
|
18
119
|
@endpoint = Async::HTTP::Endpoint.parse(BASE_URL, timeout: @timeout)
|
|
19
120
|
@client = Async::HTTP::Client.new(@endpoint)
|
|
20
121
|
end
|
|
21
|
-
|
|
122
|
+
|
|
22
123
|
def call(method, params = {})
|
|
23
124
|
with_retry do
|
|
24
125
|
make_request(method, params)
|
|
25
126
|
end
|
|
26
127
|
end
|
|
27
|
-
|
|
128
|
+
|
|
28
129
|
def call!(method, params = {}, &callback)
|
|
29
130
|
return unless callback
|
|
131
|
+
|
|
30
132
|
begin
|
|
31
133
|
result = call(method, params)
|
|
32
134
|
callback.call(result, nil)
|
|
@@ -34,38 +136,45 @@ module Telegem
|
|
|
34
136
|
callback.call(nil, error)
|
|
35
137
|
end
|
|
36
138
|
end
|
|
37
|
-
|
|
139
|
+
|
|
38
140
|
def upload(method, params)
|
|
39
141
|
with_retry do
|
|
40
142
|
url = "/bot#{@token}/#{method}"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
143
|
+
|
|
144
|
+
form = MultipartForm.new
|
|
145
|
+
|
|
44
146
|
params.each do |key, value|
|
|
45
|
-
|
|
46
|
-
body.add(key.to_s, value, filename: File.basename(value))
|
|
47
|
-
else
|
|
48
|
-
body.add(key.to_s, value.to_s)
|
|
49
|
-
end
|
|
147
|
+
form.add(key.to_s, value)
|
|
50
148
|
end
|
|
51
|
-
|
|
52
|
-
|
|
149
|
+
|
|
150
|
+
body = form.body
|
|
151
|
+
|
|
152
|
+
response = @client.post(
|
|
153
|
+
url,
|
|
154
|
+
{
|
|
155
|
+
"content-type" => form.content_type,
|
|
156
|
+
"content-length" => body.bytesize.to_s
|
|
157
|
+
},
|
|
158
|
+
body
|
|
159
|
+
)
|
|
160
|
+
|
|
53
161
|
handle_response(response)
|
|
54
162
|
end
|
|
55
163
|
end
|
|
56
|
-
|
|
164
|
+
|
|
57
165
|
def download(file_id, destination_path = nil)
|
|
58
166
|
with_retry do
|
|
59
|
-
file_info = call(
|
|
60
|
-
return nil unless file_info && file_info[
|
|
61
|
-
|
|
62
|
-
file_path = file_info[
|
|
167
|
+
file_info = call("getFile", file_id: file_id)
|
|
168
|
+
return nil unless file_info && file_info["file_path"]
|
|
169
|
+
|
|
170
|
+
file_path = file_info["file_path"]
|
|
63
171
|
download_url = "/file/bot#{@token}/#{file_path}"
|
|
64
|
-
|
|
172
|
+
|
|
65
173
|
response = @client.get(download_url)
|
|
66
|
-
|
|
174
|
+
|
|
67
175
|
if response.status == 200
|
|
68
176
|
content = response.read
|
|
177
|
+
|
|
69
178
|
if destination_path
|
|
70
179
|
File.binwrite(destination_path, content)
|
|
71
180
|
destination_path
|
|
@@ -77,78 +186,90 @@ module Telegem
|
|
|
77
186
|
end
|
|
78
187
|
end
|
|
79
188
|
end
|
|
80
|
-
|
|
189
|
+
|
|
81
190
|
def get_updates(offset: nil, timeout: 30, limit: 100, allowed_updates: nil)
|
|
82
|
-
params = {
|
|
191
|
+
params = {
|
|
192
|
+
timeout: timeout,
|
|
193
|
+
limit: limit
|
|
194
|
+
}
|
|
195
|
+
|
|
83
196
|
params[:offset] = offset if offset
|
|
84
197
|
params[:allowed_updates] = allowed_updates if allowed_updates
|
|
85
|
-
|
|
198
|
+
|
|
199
|
+
call("getUpdates", params)
|
|
86
200
|
end
|
|
87
|
-
|
|
201
|
+
|
|
88
202
|
def close
|
|
89
203
|
@client.close
|
|
90
204
|
end
|
|
91
|
-
|
|
205
|
+
|
|
92
206
|
private
|
|
93
|
-
|
|
94
|
-
def with_retry
|
|
207
|
+
|
|
208
|
+
def with_retry
|
|
95
209
|
retries = 0
|
|
210
|
+
|
|
96
211
|
begin
|
|
97
|
-
|
|
212
|
+
yield
|
|
98
213
|
rescue NetworkError, Async::TimeoutError => e
|
|
99
214
|
retries += 1
|
|
215
|
+
|
|
100
216
|
if retries <= @retries
|
|
101
217
|
@logger.warn("API request failed: #{e.message}. Retry #{retries}/#{@retries}") if @logger
|
|
102
|
-
sleep
|
|
218
|
+
sleep(@retry_delay * retries)
|
|
103
219
|
retry
|
|
104
220
|
else
|
|
105
221
|
raise
|
|
106
222
|
end
|
|
107
|
-
rescue APIError
|
|
108
|
-
# Don't retry API errors (bad request, unauthorized, etc.)
|
|
223
|
+
rescue APIError
|
|
109
224
|
raise
|
|
110
225
|
end
|
|
111
226
|
end
|
|
112
|
-
|
|
227
|
+
|
|
113
228
|
def make_request(method, params)
|
|
114
229
|
url = "/bot#{@token}/#{method}"
|
|
115
|
-
|
|
116
|
-
|
|
230
|
+
|
|
231
|
+
@logger.debug("API call #{method}") if @logger
|
|
232
|
+
|
|
117
233
|
response = @client.post(
|
|
118
234
|
url,
|
|
119
|
-
{
|
|
235
|
+
{
|
|
236
|
+
"content-type" => "application/json"
|
|
237
|
+
},
|
|
120
238
|
JSON.dump(params.compact)
|
|
121
239
|
)
|
|
122
|
-
|
|
240
|
+
|
|
123
241
|
handle_response(response)
|
|
124
242
|
end
|
|
125
|
-
|
|
243
|
+
|
|
126
244
|
def handle_response(response)
|
|
127
245
|
json = JSON.parse(response.read)
|
|
128
|
-
|
|
129
|
-
if json
|
|
130
|
-
json[
|
|
246
|
+
|
|
247
|
+
if json["ok"]
|
|
248
|
+
json["result"]
|
|
131
249
|
else
|
|
132
|
-
error_msg = json
|
|
250
|
+
error_msg = json["description"] || "HTTP #{response.status}"
|
|
133
251
|
raise APIError.new(error_msg, response.status)
|
|
134
252
|
end
|
|
135
253
|
end
|
|
136
|
-
|
|
254
|
+
|
|
137
255
|
def file_object?(obj)
|
|
138
|
-
obj.is_a?(File) ||
|
|
139
|
-
|
|
256
|
+
obj.is_a?(File) ||
|
|
257
|
+
obj.is_a?(StringIO) ||
|
|
258
|
+
obj.is_a?(Tempfile) ||
|
|
259
|
+
(obj.is_a?(String) && File.file?(obj))
|
|
140
260
|
end
|
|
141
261
|
end
|
|
142
|
-
|
|
262
|
+
|
|
143
263
|
class APIError < StandardError
|
|
144
264
|
attr_reader :code
|
|
145
|
-
|
|
265
|
+
|
|
146
266
|
def initialize(message, code = nil)
|
|
147
267
|
super(message)
|
|
148
268
|
@code = code
|
|
149
269
|
end
|
|
150
270
|
end
|
|
151
|
-
|
|
152
|
-
class NetworkError < APIError
|
|
271
|
+
|
|
272
|
+
class NetworkError < APIError
|
|
273
|
+
end
|
|
153
274
|
end
|
|
154
|
-
end
|
|
275
|
+
end
|
data/lib/api/types.rb
CHANGED
|
@@ -53,10 +53,7 @@ module Telegem
|
|
|
53
53
|
elsif @_raw_data.key?(camel_key)
|
|
54
54
|
define_singleton_method(name) { @_raw_data[camel_key] }
|
|
55
55
|
else
|
|
56
|
-
define_singleton_method(name)
|
|
57
|
-
raise NoMethodError,
|
|
58
|
-
"undefined method `#{name}' for #{self.class} with keys: #{@_raw_data.keys}"
|
|
59
|
-
end
|
|
56
|
+
define_singleton_method(name) { nil }
|
|
60
57
|
end
|
|
61
58
|
|
|
62
59
|
@_accessors_defined[name] = true
|
data/lib/core/context.rb
CHANGED
|
@@ -124,6 +124,62 @@ module Telegem
|
|
|
124
124
|
params = { chat_id: chat.id, text: text }.merge(options)
|
|
125
125
|
@bot.api.call('sendMessage', params)
|
|
126
126
|
end
|
|
127
|
+
|
|
128
|
+
def reply_rich(rich_message, **options)
|
|
129
|
+
return nil unless chat
|
|
130
|
+
|
|
131
|
+
params = { chat_id: chat.id, rich_message: rich_message }.merge(options)
|
|
132
|
+
@bot.api.call('sendRichMessage', params)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Draft streaming support (Bot API 10.1)
|
|
136
|
+
def start_draft(initial_text = "", **options)
|
|
137
|
+
return nil unless chat
|
|
138
|
+
|
|
139
|
+
draft_id = "draft_#{chat.id}_#{Time.now.to_i}_#{rand(1000)}"
|
|
140
|
+
session[:telegem_draft_id] = draft_id
|
|
141
|
+
|
|
142
|
+
rich_message = { blocks: [{ type: "paragraph", content: initial_text }] }
|
|
143
|
+
params = { chat_id: chat.id, draft_id: draft_id, rich_message: rich_message }.merge(options)
|
|
144
|
+
@bot.api.call('sendRichMessageDraft', params)
|
|
145
|
+
|
|
146
|
+
draft_id
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def append_to_draft(draft_id = nil, content, **options)
|
|
150
|
+
return nil unless chat
|
|
151
|
+
|
|
152
|
+
draft_id ||= session[:telegem_draft_id]
|
|
153
|
+
return nil unless draft_id
|
|
154
|
+
|
|
155
|
+
rich_message = { blocks: [{ type: "paragraph", content: content }] }
|
|
156
|
+
params = { chat_id: chat.id, draft_id: draft_id, rich_message: rich_message }.merge(options)
|
|
157
|
+
@bot.api.call('sendRichMessageDraft', params)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def publish_draft(draft_id = nil, **options)
|
|
161
|
+
return nil unless chat
|
|
162
|
+
|
|
163
|
+
draft_id ||= session[:telegem_draft_id]
|
|
164
|
+
return nil unless draft_id
|
|
165
|
+
|
|
166
|
+
params = { chat_id: chat.id, draft_id: draft_id }.merge(options)
|
|
167
|
+
result = @bot.api.call('publishRichMessageDraft', params)
|
|
168
|
+
session.delete(:telegem_draft_id)
|
|
169
|
+
result
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def cancel_draft(draft_id = nil, **options)
|
|
173
|
+
return nil unless chat
|
|
174
|
+
|
|
175
|
+
draft_id ||= session[:telegem_draft_id]
|
|
176
|
+
return nil unless draft_id
|
|
177
|
+
|
|
178
|
+
params = { chat_id: chat.id, draft_id: draft_id }.merge(options)
|
|
179
|
+
result = @bot.api.call('cancelRichMessageDraft', params)
|
|
180
|
+
session.delete(:telegem_draft_id)
|
|
181
|
+
result
|
|
182
|
+
end
|
|
127
183
|
|
|
128
184
|
def edit_message_text(text, **options)
|
|
129
185
|
return nil unless message && chat
|
data/lib/telegem.rb
CHANGED
data/lib/webhook/server.rb
CHANGED
|
@@ -104,28 +104,38 @@ module Telegem
|
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
def handle_request(request)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
107
|
+
begin
|
|
108
|
+
case request.path
|
|
109
|
+
when @secret_token, "/#{@secret_token}"
|
|
110
|
+
handle_webhook_request(request)
|
|
111
|
+
when '/health', '/healthz'
|
|
112
|
+
health_endpoint(request)
|
|
113
|
+
else
|
|
114
|
+
[404, {}, ["Not Found"]]
|
|
115
|
+
end
|
|
116
|
+
rescue => e
|
|
117
|
+
@logger.error("Request handler error: #{e.class} - #{e.message}\n#{e.backtrace.join("\n")}")
|
|
118
|
+
[500, {}, ["Internal Server Error"]]
|
|
114
119
|
end
|
|
115
120
|
end
|
|
116
121
|
|
|
117
122
|
def handle_webhook_request(request)
|
|
118
123
|
return [405, {}, ["Method Not Allowed"]] unless request.post?
|
|
124
|
+
|
|
119
125
|
received = request.headers['X-Telegram-Bot-Api-Secret-Token'] ||
|
|
120
|
-
|
|
121
|
-
return [403, {}, ["Forbidden"]] unless received
|
|
126
|
+
request.headers['x-telegram-bot-api-secret-token']
|
|
127
|
+
return [403, {}, ["Forbidden"]] unless received == @secret_token
|
|
122
128
|
|
|
123
129
|
begin
|
|
124
130
|
body = request.body.read
|
|
125
|
-
update_data = JSON.parse(body)
|
|
126
|
-
|
|
131
|
+
update_data = json_to_symbols(JSON.parse(body))
|
|
132
|
+
process_webhook_update(update_data)
|
|
127
133
|
[200, {}, ["OK"]]
|
|
128
|
-
rescue
|
|
134
|
+
rescue JSON::ParserError => e
|
|
135
|
+
@logger.error("JSON parse error: #{e}")
|
|
136
|
+
[400, {}, ["Bad Request"]]
|
|
137
|
+
rescue => e
|
|
138
|
+
@logger.error("Webhook handler error: #{e.class} - #{e.message}")
|
|
129
139
|
[500, {}, ["Internal Server Error"]]
|
|
130
140
|
end
|
|
131
141
|
end
|
|
@@ -137,11 +147,12 @@ module Telegem
|
|
|
137
147
|
end
|
|
138
148
|
|
|
139
149
|
def health_endpoint(request)
|
|
140
|
-
|
|
150
|
+
body = {
|
|
141
151
|
status: 'ok',
|
|
142
152
|
mode: @ssl_mode.to_s,
|
|
143
153
|
ssl: @ssl_mode != :none
|
|
144
|
-
}.to_json
|
|
154
|
+
}.to_json
|
|
155
|
+
[200, { 'Content-Type' => 'application/json' }, [body]]
|
|
145
156
|
end
|
|
146
157
|
|
|
147
158
|
def stop
|
|
@@ -183,6 +194,17 @@ module Telegem
|
|
|
183
194
|
def running?
|
|
184
195
|
@running
|
|
185
196
|
end
|
|
197
|
+
|
|
198
|
+
def json_to_symbols(obj)
|
|
199
|
+
case obj
|
|
200
|
+
when Hash
|
|
201
|
+
obj.transform_keys { |k| k.to_sym }.transform_values { |v| json_to_symbols(v) }
|
|
202
|
+
when Array
|
|
203
|
+
obj.map { |v| json_to_symbols(v) }
|
|
204
|
+
else
|
|
205
|
+
obj
|
|
206
|
+
end
|
|
207
|
+
end
|
|
186
208
|
end
|
|
187
209
|
end
|
|
188
210
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: telegem
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- zendrx
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: securerandom
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
47
|
+
version: '0.8'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
54
|
+
version: '0.8'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: pdf-reader
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '1.50'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: logger
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '1.6'
|
|
118
|
+
type: :runtime
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '1.6'
|
|
111
125
|
description: |
|
|
112
126
|
Telegem is a modern Telegram Bot Framework for Ruby inspired by Telegraf.js.
|
|
113
127
|
Built with async-first design using async-http, featuring scenes, middleware,
|
|
@@ -119,14 +133,14 @@ executables:
|
|
|
119
133
|
extensions: []
|
|
120
134
|
extra_rdoc_files: []
|
|
121
135
|
files:
|
|
136
|
+
- ".anv"
|
|
122
137
|
- ".rubocop.yml"
|
|
123
138
|
- CHANGELOG.md
|
|
124
|
-
- CODE_OF_CONDUCT.md
|
|
125
139
|
- Gemfile
|
|
126
|
-
- Gemfile.lock
|
|
127
140
|
- LICENSE
|
|
128
141
|
- README.md
|
|
129
142
|
- Starts_HallofFame.md
|
|
143
|
+
- _config.yml
|
|
130
144
|
- assets/.gitkeep
|
|
131
145
|
- assets/logo.png
|
|
132
146
|
- bin/.gitkeep
|
|
@@ -186,7 +200,7 @@ metadata:
|
|
|
186
200
|
documentation_uri: https://github.com/slick-lab/telegem/tree/main/docs
|
|
187
201
|
rubygems_mfa_required: 'false'
|
|
188
202
|
post_install_message: |
|
|
189
|
-
Thanks for installing Telegem 3.
|
|
203
|
+
Thanks for installing Telegem 3.6.0!
|
|
190
204
|
|
|
191
205
|
Documentation: https://github.com/slick-lab/telegem
|
|
192
206
|
|
|
@@ -203,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
203
217
|
requirements:
|
|
204
218
|
- - ">="
|
|
205
219
|
- !ruby/object:Gem::Version
|
|
206
|
-
version: 3.
|
|
220
|
+
version: 3.2.0
|
|
207
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
208
222
|
requirements:
|
|
209
223
|
- - ">="
|
data/CODE_OF_CONDUCT.md
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Contributor Covenant Code of Conduct
|
|
2
|
-
|
|
3
|
-
## Our Pledge
|
|
4
|
-
We pledge to make participation in our project a harassment-free experience for everyone...
|
|
5
|
-
|
|
6
|
-
## Our Standards
|
|
7
|
-
Examples of behavior that contributes to a positive environment...
|
|
8
|
-
|
|
9
|
-
## Enforcement
|
|
10
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported...
|
|
11
|
-
|
|
12
|
-
## Attribution
|
|
13
|
-
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org)...
|