telegem 3.2.0 → 3.2.2

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: 3e8ecb3c22ffef3476d429d9631a12b953f15c0b3b0b3d41970af0539b8627fd
4
- data.tar.gz: ee9b68ccc7f97d6a5916e99d6d0d57ce6e5f7d311493ed6265f0bfd81393f140
3
+ metadata.gz: 3e38340f8acfbe77b677a30960ba7f5f7e074b7fe373890b676d492f30141207
4
+ data.tar.gz: 9ad810bb1fb0e63af1de6a1120f8adcc791e2c40765446731e67eee2d4b82d6a
5
5
  SHA512:
6
- metadata.gz: 32f1f42950ab56a207c62c00f90104275cb6e9f68726d2650b244b01443a88e654f3b78af837753096a6fcfc6264cb0ab85064ec14cc44032b8ee01b46ab4e24
7
- data.tar.gz: '0498f7e735278a6cb66b4a33c770534f92d0638fd196bda2aae5fbf547901b7b86a65d02b183d058b6d6791d35de09d540b4498fa24a51319c84c03a2a9ab731'
6
+ metadata.gz: ebea1b6df44831d3fbb912f345cce9f5bee57f9e887fa39df1f7dd8056b5a360f7703b56c5f591de17e13aa105b9a911737c00364bc48ea21af974dcf19382c1
7
+ data.tar.gz: 2727f777908d295aff07fe535c11a5a6238cb841e2f4944ca7b26973ed87cb140671aa45cc2d3cf937cc422a507b31b7f69e165e1641c5255691bc2d930b7060
data/Readme.md CHANGED
@@ -108,7 +108,7 @@ Perfect For:
108
108
 
109
109
  ---
110
110
 
111
- 📚 Documentation
111
+ [📚 Documentation](https://www.rubydoc.info/gems/telegem/3.2.0/index)
112
112
 
113
113
 
114
114
 
data/bin/telegem-ssl CHANGED
File without changes
data/lib/core/bot.rb CHANGED
@@ -197,6 +197,8 @@ module Telegem
197
197
  update = Types::Update.new(update_data)
198
198
  process_update(update)
199
199
  end
200
+
201
+
200
202
 
201
203
  private
202
204
 
data/lib/core/context.rb CHANGED
@@ -42,6 +42,82 @@ module Telegem
42
42
  inline_query&.query
43
43
  end
44
44
 
45
+ def message_id
46
+ message&.message_id
47
+ end
48
+
49
+ def message_date
50
+ message&.date
51
+ end
52
+
53
+ def edit_date
54
+ message&.edit_date
55
+ end
56
+
57
+ def command_name
58
+ message&.command_name
59
+ end
60
+
61
+ def has_media?
62
+ message&.has_media? || false
63
+ end
64
+
65
+ def media_type
66
+ message&.media_type
67
+ end
68
+
69
+ def entities
70
+ message&.entities || []
71
+ end
72
+
73
+ def caption_entities
74
+ message&caption_entities || []
75
+ end
76
+
77
+ def caption
78
+ message&.caption
79
+ end
80
+
81
+ def reply?
82
+ message&.reply?
83
+ end
84
+
85
+ def replied_message
86
+ message&.reply_to_message
87
+ end
88
+
89
+ def replied_text
90
+ replied_message&.text
91
+ end
92
+
93
+ def replied_from
94
+ replied_message&.from
95
+ end
96
+
97
+ def replied_chat
98
+ replied_message&.chat
99
+ end
100
+
101
+ def update_type
102
+ @update.type
103
+ end
104
+
105
+ def is_edited?
106
+ !!@update.edited_message
107
+ end
108
+
109
+ def channel_post?
110
+ update_type == :channel_post
111
+ end
112
+
113
+ def callback_query?
114
+ update_type == :callback_query
115
+ end
116
+
117
+ def inline_query?
118
+ update_type == :inline_query
119
+ end
120
+
45
121
  def reply(text, **options)
46
122
  return nil unless chat
47
123
 
@@ -88,7 +88,8 @@ module Telegem
88
88
  end
89
89
 
90
90
  def cleanup_counter(type, key, now)
91
-
91
+ expires = @counters[type].get_ttl(key) || now
92
+ @counters[type].delete(key) if now > expires
92
93
  end
93
94
 
94
95
  def rate_limit_response(ctx)
@@ -96,5 +97,5 @@ module Telegem
96
97
  ctx.reply("⏳ Please wait a moment before sending another request.") rescue nil
97
98
  nil
98
99
  end
99
- end
100
+ end
100
101
  end
@@ -152,16 +152,13 @@ module Telegem
152
152
  end
153
153
 
154
154
  def to_h
155
- # Keep only hash buttons
156
- clean_rows = @buttons.map do |row|
157
- row = row.is_a?(Array) ? row : [row]
158
- row.select { |btn| btn.is_a?(Hash) }
159
- end.reject(&:empty?)
160
-
161
- {
162
- inline_keyboard: clean_rows
163
- }
164
- end
155
+ clean_rows = @buttons.compact.map do |row|
156
+ row = Array(row).compact.select { |btn| is_a?(Hash) }
157
+ row.empty? ? nil : row
158
+ end.compact
159
+ { inline_keyboard: clean_rows}
160
+ end
161
+
165
162
  def to_json(*args)
166
163
  to_h.to_json(*args)
167
164
  end
@@ -1,97 +1,203 @@
1
- require 'json'
1
+ #frozen_string_literal: true
2
2
  require 'pdf/reader'
3
-
3
+ require 'json'
4
+ require 'tempfile'
5
+ require 'securerandom'
4
6
  module Telegem
5
7
  module Plugins
6
- class FileExtractor
8
+ class FileExtract
7
9
  def initialize(bot, file_id, **options)
8
10
  @bot = bot
9
11
  @file_id = file_id
10
12
  @options = {
11
- timeout: 15,
12
13
  auto_delete: true,
13
- file_type: nil
14
+ max_file_size: 50 * 1024 * 1024,
15
+ timeout: 60
14
16
  }.merge(options)
15
- file_path = "temp/#{@file_id}"
16
- download_file(file_path)
17
+ @temp_file = nil
18
+ @detected_type = nil
19
+ end
20
+ def extract
21
+ download_if_needed
22
+ detect_type
23
+ case @detected_type
24
+ when :pdf then extract_pdf
25
+ when :json then extract_json
26
+ when :html then extract_html
27
+ when :txt, :md, :csv then extract_text
28
+ else
29
+ {
30
+ success: false,
31
+ error: "Unsupported file type: #{@detected_type}"
32
+ }
33
+ end
34
+ end
35
+ private
36
+ def download_if_needed
37
+ return if @temp_file
38
+ @temp_file = Tempfile.new(['telegem_', SecureRandom.hex(6)])
39
+ unless
40
+ @bot.api.download(@file_id, @temp_file.path)
41
+ raise "Failed to download file with ID #{@file_id}"
42
+ end
43
+ @temp_file.close
17
44
  end
18
-
19
- def download_file(file_path)
20
- if @options[:file_type] == :pdf
21
- extract_pdf(file_path)
22
- elsif @options[:file_type] == :json
23
- extract_json(file_path)
24
- elsif @options[:file_type] == :html
25
- extract_html(file_path)
26
- elsif @options[:file_type] == :txt
27
- extract_text(file_path)
28
- else
29
- { error: "unsupported file type" }
45
+ def detect_type
46
+ return @detected_type if @detected_type
47
+ pll = File.read(@temp_file.path, 10) rescue nil
48
+ case pll
49
+ when "%PDF" then @detected_type = :pdf
50
+ when "{", "[" then @detected_type = :json
51
+ when "<!DO", "<ht" then @detected_type = :html
52
+ else
53
+ ext = File.extname(@temp_file.path).downcase
54
+ @detected_type = case ext
55
+ when ".txt" then :txt
56
+ when ".md" then :md
57
+ when ".csv" then :csv
58
+ else :unknown
59
+ end
30
60
  end
61
+ @detected_type
31
62
  end
32
-
33
- def extract_pdf(file_path)
34
- begin
35
- @bot.api.download(@file_id, "#{file_path}.pdf")
36
- reader = PDF::Reader.new("#{file_path}.pdf")
37
- text = reader.pages.map(&:text).join("\n").strip
38
-
39
- if text.empty?
40
- { error: "pdf is empty" }
41
- else
42
- result = {
43
- success: true,
44
- content: text,
45
- pages: reader.page_count,
63
+ def extract_pdf
64
+ begin
65
+ reader = PDF::Reader.new(@temp_file.path)
66
+ text = reader.pages.map(&:text).join("\n")
67
+ if text.strip.empty?
68
+ return {
69
+ success: false,
70
+ error: "PDF contains no extractable text"
46
71
  }
47
- File.delete("#{file_path}.pdf") if @options[:auto_delete]
48
- result
49
- end
50
- rescue PDF::Reader::MalformedPDFError
51
- { error: "malformed pdf format" }
52
- rescue PDF::Reader::EncryptedPDFError
53
- { error: "encrypted pdf" }
72
+ else
73
+ {
74
+ success: true,
75
+ type: :pdf,
76
+ content: text,
77
+ metadata: {
78
+ page_count: reader.page_count,
79
+ info: reader.info
80
+ }
81
+ }
82
+ end
54
83
  rescue => e
55
- { error: "pdf processing failed #{e.message}" }
56
- ensure
57
- File.delete("#{file_path}.pdf") if @options[:auto_delete] && File.exist?("#{file_path}.pdf")
84
+ {
85
+ success: false,
86
+ error: "Failed to extract PDF: #{e.message}"
87
+ }
88
+ rescue LoadError
89
+ {
90
+ success: false,
91
+ error: "PDF extraction requires the 'pdf-reader' gem. Please add it to your Gemfile."
92
+ }
93
+ rescue PDF::Reader::MalformedPDFError => e
94
+ {
95
+ success: false,
96
+ error: "Malformed PDF: #{e.message}"
97
+ }
98
+ rescue PDF::Reader::UnsupportedFeatureError => e
99
+ {
100
+ success: false,
101
+ error: "Unsupported PDF feature: #{e.message}"
102
+ }
103
+ rescue PDF::Reader::EncryptedPDFError => e
104
+ {
105
+ success: false,
106
+ error: "Encrypted PDF: #{e.message}"
107
+ }
108
+ ensure
109
+ cleanup if @options[:auto_delete]
58
110
  end
59
- end
111
+ end
112
+ def extract_json
113
+ begin
114
+ content = File.read(@temp_file.path)
115
+ data = JSON.parse(content)
116
+ if data.nil? || (data.is_a?(Hash) && data.empty?) || (data.is_a?(Array) && data.empty?)
117
+ return {
118
+ success: false,
119
+ error: "JSON file is empty or contains no data"
120
+ }
121
+ else
122
+ {
123
+ success: true,
124
+ type: :json,
125
+ content: data,
126
+ metadata: {
127
+ size: content.size,
128
+ keys: data.is_a?(Hash) ? data.keys : nil,
129
+ length: data.is_a?(Array) ? data.length : nil
130
+ }
131
+ }
132
+ end
133
+ rescue JSON::ParserError => e
134
+ {
135
+ success: false,
136
+ error: "Invalid JSON format: #{e.message}"
137
+ }
138
+ ensure
139
+ cleanup if @options[:auto_delete]
140
+ end
60
141
 
61
- def extract_json(file_path)
62
- @bot.api.download(@file_id, "#{file_path}.json")
63
- json_data = JSON.parse(File.read("#{file_path}.json"))
64
- if File.exist?("#{file_path}.json")
142
+ def extract_html
143
+ begin
144
+ content = File.read(@temp_file.path)
145
+ if content.strip.empty?
146
+ return {
147
+ success: false,
148
+ error: "HTML file is empty"
149
+ }
150
+ end
65
151
  {
66
152
  success: true,
67
- content: json_data
153
+ type: :html,
154
+ content: content,
155
+ metadata: {
156
+ size: content.size,
157
+ title: content[/<title>(.*?)<\/title>/i, 1]
158
+ }
68
159
  }
69
- else
160
+ rescue => e
70
161
  {
71
- error: "no json file"
162
+ success: false,
163
+ error: "Failed to extract HTML: #{e.message}"
72
164
  }
165
+ ensure
166
+ cleanup if @options[:auto_delete]
73
167
  end
74
168
  end
75
-
76
- def extract_html(file_path)
77
- destination = "#{file_path}.html"
78
- @bot.api.download(@file_id, destination)
79
- html = File.read(destination)
80
- if html.empty?
169
+ def extract_text
170
+ begin
171
+ content = File.read(@temp_file.path)
172
+ if content.strip.empty?
173
+ return {
174
+ success: false,
175
+ error: "Text file is empty"
176
+ }
177
+ end
81
178
  {
82
- error: "html content is empty"
179
+ success: true,
180
+ type: :text,
181
+ content: content,
182
+ metadata: {
183
+ size: content.size,
184
+ line_count: content.lines.count
185
+ }
83
186
  }
84
- else
187
+ rescue => e
85
188
  {
86
- success: true,
87
- content: html
189
+ success: false,
190
+ error: "Failed to extract text: #{e.message}"
88
191
  }
192
+ ensure
193
+ cleanup if @options[:auto_delete]
89
194
  end
90
- rescue => e
91
- {
92
- error: "error #{e.message}"
93
- }
195
+ end
196
+ def cleanup
197
+ @temp_file.unlink if @temp_file
198
+ @temp_file = nil
94
199
  end
95
200
  end
96
201
  end
97
- end
202
+ end
203
+ end
@@ -0,0 +1,8 @@
1
+ {
2
+ "folders": [
3
+ {
4
+ "path": ".."
5
+ }
6
+ ],
7
+ "settings": {}
8
+ }
data/lib/telegem.rb CHANGED
@@ -3,7 +3,7 @@ require 'logger'
3
3
  require 'json'
4
4
 
5
5
  module Telegem
6
- VERSION = "3.2.0".freeze
6
+ VERSION = "3.2.2".freeze
7
7
  end
8
8
 
9
9
  # Load core components
@@ -82,4 +82,4 @@ if ENV['TELEGEM_GLOBAL'] == 'true'
82
82
  def Telegem(token, **options)
83
83
  ::Telegem.new(token, **options)
84
84
  end
85
- end
85
+ 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.2.0
4
+ version: 3.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - sick_phantom
@@ -13,72 +13,100 @@ dependencies:
13
13
  name: httpx
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - ">="
16
+ - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
18
+ version: '1.0'
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: '1.0'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: concurrent-ruby
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
- - - ">="
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: securerandom
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
31
45
  - !ruby/object:Gem::Version
32
- version: '0'
46
+ version: '0.1'
33
47
  type: :runtime
34
48
  prerelease: false
35
49
  version_requirements: !ruby/object:Gem::Requirement
36
50
  requirements:
37
- - - ">="
51
+ - - "~>"
38
52
  - !ruby/object:Gem::Version
39
- version: '0'
53
+ version: '0.1'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: async
42
56
  requirement: !ruby/object:Gem::Requirement
43
57
  requirements:
44
- - - ">="
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.0'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: async-http
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
45
73
  - !ruby/object:Gem::Version
46
- version: '0'
74
+ version: '0.100'
47
75
  type: :runtime
48
76
  prerelease: false
49
77
  version_requirements: !ruby/object:Gem::Requirement
50
78
  requirements:
51
- - - ">="
79
+ - - "~>"
52
80
  - !ruby/object:Gem::Version
53
- version: '0'
81
+ version: '0.100'
54
82
  - !ruby/object:Gem::Dependency
55
83
  name: pdf-reader
56
84
  requirement: !ruby/object:Gem::Requirement
57
85
  requirements:
58
- - - ">="
86
+ - - "~>"
59
87
  - !ruby/object:Gem::Version
60
- version: '0'
88
+ version: '2.0'
61
89
  type: :runtime
62
90
  prerelease: false
63
91
  version_requirements: !ruby/object:Gem::Requirement
64
92
  requirements:
65
- - - ">="
93
+ - - "~>"
66
94
  - !ruby/object:Gem::Version
67
- version: '0'
95
+ version: '2.0'
68
96
  - !ruby/object:Gem::Dependency
69
97
  name: docx
70
98
  requirement: !ruby/object:Gem::Requirement
71
99
  requirements:
72
- - - ">="
100
+ - - "~>"
73
101
  - !ruby/object:Gem::Version
74
- version: '0'
102
+ version: '0.3'
75
103
  type: :runtime
76
104
  prerelease: false
77
105
  version_requirements: !ruby/object:Gem::Requirement
78
106
  requirements:
79
- - - ">="
107
+ - - "~>"
80
108
  - !ruby/object:Gem::Version
81
- version: '0'
109
+ version: '0.3'
82
110
  - !ruby/object:Gem::Dependency
83
111
  name: rspec
84
112
  requirement: !ruby/object:Gem::Requirement
@@ -145,6 +173,7 @@ files:
145
173
  - lib/session/memory_store.rb
146
174
  - lib/session/middleware.rb
147
175
  - lib/session/scene_middleware.rb
176
+ - lib/telegem.code-workspace
148
177
  - lib/telegem.rb
149
178
  - lib/webhook/.gitkeep
150
179
  - lib/webhook/server.rb
@@ -153,13 +182,13 @@ homepage: https://gitlab.com/ruby-telegem/telegem
153
182
  licenses:
154
183
  - MIT
155
184
  metadata:
156
- homepage_uri: https://gitlab.com/ruby-telegem/telegem
185
+ homepage_uri: https://gitlab.com/ruby-telegem/telegem/-/blob/main/README.md
157
186
  source_code_uri: https://gitlab.com/ruby-telegem/telegem
158
187
  changelog_uri: https://gitlab.com/ruby-telegem/telegem/-/blob/main/CHANGELOG.md
159
188
  bug_tracker_uri: https://gitlab.com/ruby-telegem/telegem/-/issues
160
189
  documentation_uri: https://gitlab.com/ruby-telegem/telegem/-/tree/main/docs-src?ref_type=heads
161
190
  rubygems_mfa_required: 'false'
162
- post_install_message: "Thanks for installing Telegem 3.2.0!\n\n\U0001F4DA Documentation:
191
+ post_install_message: "Thanks for installing Telegem 3.2.2!\n\n\U0001F4DA Documentation:
163
192
  https://gitlab.com/ruby-telegem/telegem\n\n\U0001F510 For SSL Webhooks:\nRun: telegem-ssl
164
193
  your-domain.com\nThis sets up Let's Encrypt certificates automatically.\n\n\U0001F916
165
194
  Happy bot building!\n"