telepost 0.8.1 → 0.9.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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +22 -28
  3. data/README.md +11 -1
  4. data/lib/telepost.rb +64 -10
  5. data/telepost.gemspec +1 -1
  6. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72e3854ed2c2ef04727919095d396357f7cd91641387825a039d28cafdf819cf
4
- data.tar.gz: 4ef6fe085695c41b615dbc31ce0c885c966ecd357e361625e91d74aad61a07a4
3
+ metadata.gz: 847510fbfea002fc65ee0a20dbc39dd2c5ede53aab590c5a8aa2ed66f2bdc50e
4
+ data.tar.gz: '086d01f73bff093ef51dbbcb67757d48d21a37211131ca6522e5b2f25901345b'
5
5
  SHA512:
6
- metadata.gz: 29ef8828ecfb355777daffb9a8a69fffd59b3393357bd60bc9b5012a9be6062c67ffd0660cd6d4bbd5c9a5effec7ef4a4c1bafbed5be7801b4494b935c1a3db2
7
- data.tar.gz: 9e5aab74dccdca37292a2eb5959c2b24396cddfdd6189de47445ad0e48194efee77dbc3a7728303a70d1860f8f80984a9809794cdfecdf0440b5fb929d6effae
6
+ metadata.gz: 77b5815fcaa702a9a0c422b7633e4992cb7824d79e0c0eb0a77ce03bd4e58464463eab5a3a154e47c4aad0704601d9fc7fa43c1c3fb2656401e88d1d4bd4df04
7
+ data.tar.gz: 4e9334873a9a5e0e9e7c92828b657fbc00b9f822e6c471f6c57bc7b582e3a54b6c6dde6a3c332de43614cffe7c31485678f8206f8fff7ee185ba9c6dc1f65142
data/Gemfile.lock CHANGED
@@ -11,25 +11,25 @@ GEM
11
11
  public_suffix (>= 2.0.2, < 8.0)
12
12
  ansi (1.6.0)
13
13
  ast (2.4.3)
14
- bigdecimal (4.1.0)
14
+ bigdecimal (4.1.2)
15
15
  builder (3.3.0)
16
- concurrent-ruby (1.3.5)
16
+ concurrent-ruby (1.3.6)
17
17
  crack (1.0.1)
18
18
  bigdecimal
19
19
  rexml
20
20
  docile (1.4.1)
21
21
  drb (2.2.3)
22
- dry-core (1.1.0)
22
+ dry-core (1.2.0)
23
23
  concurrent-ruby (~> 1.0)
24
24
  logger
25
25
  zeitwerk (~> 2.6)
26
- dry-inflector (1.2.0)
26
+ dry-inflector (1.3.1)
27
27
  dry-logic (1.6.0)
28
28
  bigdecimal
29
29
  concurrent-ruby (~> 1.0)
30
30
  dry-core (~> 1.1)
31
31
  zeitwerk (~> 2.6)
32
- dry-struct (1.8.0)
32
+ dry-struct (1.8.1)
33
33
  dry-core (~> 1.1)
34
34
  dry-types (~> 1.8, >= 1.8.2)
35
35
  ice_nine (~> 0.11)
@@ -41,26 +41,21 @@ GEM
41
41
  dry-inflector (~> 1.0)
42
42
  dry-logic (~> 1.4)
43
43
  zeitwerk (~> 2.6)
44
- faraday (2.13.2)
44
+ faraday (2.14.2)
45
45
  faraday-net_http (>= 2.0, < 3.5)
46
46
  json
47
47
  logger
48
- faraday-multipart (1.1.1)
48
+ faraday-multipart (1.2.0)
49
49
  multipart-post (~> 2.0)
50
- faraday-net_http (3.4.1)
51
- net-http (>= 0.5.0)
50
+ faraday-net_http (3.4.3)
51
+ net-http (~> 0.5)
52
52
  hashdiff (1.2.1)
53
53
  ice_nine (0.11.2)
54
- json (2.19.2)
55
- json-schema (6.2.0)
56
- addressable (~> 2.8)
57
- bigdecimal (>= 3.1, < 5)
54
+ json (2.19.5)
58
55
  language_server-protocol (3.17.0.5)
59
56
  lint_roller (1.1.0)
60
57
  logger (1.7.0)
61
- mcp (0.9.2)
62
- json-schema (>= 4.1)
63
- minitest (6.0.5)
58
+ minitest (6.0.6)
64
59
  drb (~> 2.0)
65
60
  prism (~> 1.5)
66
61
  minitest-reporters (1.8.0)
@@ -69,10 +64,10 @@ GEM
69
64
  minitest (>= 5.0, < 7)
70
65
  ruby-progressbar
71
66
  multipart-post (2.4.1)
72
- net-http (0.6.0)
73
- uri
74
- parallel (1.27.0)
75
- parser (3.3.10.2)
67
+ net-http (0.9.1)
68
+ uri (>= 0.11.1)
69
+ parallel (2.1.0)
70
+ parser (3.3.11.1)
76
71
  ast (~> 2.4.1)
77
72
  racc
78
73
  prism (1.9.0)
@@ -80,14 +75,13 @@ GEM
80
75
  racc (1.8.1)
81
76
  rainbow (3.1.1)
82
77
  rake (13.4.2)
83
- regexp_parser (2.11.3)
78
+ regexp_parser (2.12.0)
84
79
  rexml (3.4.4)
85
- rubocop (1.85.1)
80
+ rubocop (1.86.2)
86
81
  json (~> 2.3)
87
82
  language_server-protocol (~> 3.17.0.2)
88
83
  lint_roller (~> 1.1.0)
89
- mcp (~> 0.6)
90
- parallel (~> 1.10)
84
+ parallel (>= 1.10)
91
85
  parser (>= 3.3.0.2)
92
86
  rainbow (>= 2.2.2, < 4.0)
93
87
  regexp_parser (>= 2.9.3, < 3.0)
@@ -97,7 +91,7 @@ GEM
97
91
  rubocop-ast (1.49.1)
98
92
  parser (>= 3.3.7.2)
99
93
  prism (~> 1.7)
100
- rubocop-elegant (0.0.20)
94
+ rubocop-elegant (0.5.1)
101
95
  lint_roller (~> 1.1)
102
96
  rubocop (~> 1.75)
103
97
  rubocop-minitest (0.39.1)
@@ -129,13 +123,13 @@ GEM
129
123
  unicode-display_width (3.2.0)
130
124
  unicode-emoji (~> 4.1)
131
125
  unicode-emoji (4.2.0)
132
- uri (1.0.4)
126
+ uri (1.1.1)
133
127
  webmock (3.26.2)
134
128
  addressable (>= 2.8.0)
135
129
  crack (>= 0.3.2)
136
130
  hashdiff (>= 0.4.0, < 2.0.0)
137
- yard (0.9.43)
138
- zeitwerk (2.7.3)
131
+ yard (0.9.44)
132
+ zeitwerk (2.8.2)
139
133
 
140
134
  PLATFORMS
141
135
  arm64-darwin-22
data/README.md CHANGED
@@ -37,7 +37,7 @@ tp.post(12345, 'How are you?', 'How are you doing?')
37
37
  All lines you provide to the `post()` method will be concatenated
38
38
  with a space between them.
39
39
 
40
- Or you can pre-configure it to talk to certain list of chats.
40
+ Or you can pre-configure it to talk to a certain list of chats.
41
41
  Your bot has to be an admin of the channel, in order to post there.
42
42
  Here is how you "spam":
43
43
 
@@ -55,6 +55,16 @@ tp = Telepost.new('..token..')
55
55
  tp.attach(12345, '/tmp/dump.sql', caption: 'Today is dump')
56
56
  ```
57
57
 
58
+ You can also pass an array of files, to post them all as a single
59
+ grouped message (a Telegram "album"). Files with an image extension
60
+ are sent as photos, the rest as documents, and the `caption:` is
61
+ shown once, on the first item:
62
+
63
+ ```ruby
64
+ tp = Telepost.new('..token..')
65
+ tp.attach(12345, ['/tmp/a.png', '/tmp/b.png'], caption: 'Two shots')
66
+ ```
67
+
58
68
  That's it.
59
69
 
60
70
  ## How to contribute
data/lib/telepost.rb CHANGED
@@ -42,9 +42,22 @@ class Telepost
42
42
  end
43
43
 
44
44
  def attach(chat, file, caption: nil)
45
- path = file.is_a?(String) ? file : file.path
46
- tail = caption.nil? ? '' : " caption=#{caption}"
47
- @sent << "#{chat}: [attach:#{File.basename(path)}#{tail}]"
45
+ @sent <<
46
+ if file.is_a?(Array)
47
+ "#{chat}: [attach-group:#{names(file)}#{cap(caption)}]"
48
+ else
49
+ "#{chat}: [attach:#{names([file])}#{cap(caption)}]"
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def names(files)
56
+ files.map { |f| File.basename(f.is_a?(String) ? f : f.path) }.join(',')
57
+ end
58
+
59
+ def cap(caption)
60
+ caption.nil? ? '' : " caption=#{caption}"
48
61
  end
49
62
  end
50
63
 
@@ -112,18 +125,59 @@ class Telepost
112
125
  # argument can either be a path (String) or an open IO/File. The
113
126
  # filename shown in Telegram comes from the basename of the path.
114
127
  #
128
+ # When +file+ is an +Array+, all of its items are posted as a single
129
+ # grouped message (a Telegram "album") via +sendMediaGroup+. Items
130
+ # with an image extension are wrapped in +InputMediaPhoto+, the rest
131
+ # in +InputMediaDocument+. The +caption+ is attached to the first
132
+ # item only, so the album shows one caption.
133
+ #
115
134
  # @param chat [Integer, String] Chat ID or channel name
116
- # @param file [String, File, IO] Path to the file or an open IO
135
+ # @param file [String, File, IO, Array] File (or array of files) to attach
117
136
  # @param caption [String, nil] Optional caption for the attachment
118
137
  # @param parse_mode [String] Parse mode used for the caption
119
138
  # @return [Telegram::Bot::Types::Message] The sent message object
120
139
  def attach(chat, file, caption: nil, parse_mode: 'Markdown')
121
- document =
122
- if file.is_a?(String)
123
- Faraday::UploadIO.new(file, 'application/octet-stream', File.basename(file))
124
- else
125
- file
140
+ return album(chat, file, caption:, parse_mode:) if file.is_a?(Array)
141
+ io = upload(file)
142
+ @bot.api.send_document(chat_id: chat, document: io, caption:, parse_mode:)
143
+ ensure
144
+ io.close if file.is_a?(String) && io.respond_to?(:close)
145
+ end
146
+
147
+ PHOTO_EXTENSIONS = %w[.jpg .jpeg .png .gif .webp].freeze
148
+
149
+ private
150
+
151
+ def album(chat, files, caption: nil, parse_mode: 'Markdown')
152
+ opened = []
153
+ params = { chat_id: chat }
154
+ params[:media] =
155
+ files.each_with_index.map do |file, idx|
156
+ io = upload(file)
157
+ opened << io if file.is_a?(String)
158
+ params[:"file#{idx}"] = io
159
+ attrs = { media: "attach://file#{idx}" }
160
+ if idx.zero? && !caption.nil?
161
+ attrs[:caption] = caption
162
+ attrs[:parse_mode] = parse_mode
163
+ end
164
+ klass(file).new(**attrs)
126
165
  end
127
- @bot.api.send_document(chat_id: chat, document:, caption:, parse_mode:)
166
+ @bot.api.send_media_group(**params)
167
+ ensure
168
+ opened.each(&:close)
169
+ end
170
+
171
+ def upload(file)
172
+ return file unless file.is_a?(String)
173
+ Faraday::UploadIO.new(file, 'application/octet-stream', File.basename(file))
174
+ end
175
+
176
+ def klass(file)
177
+ photo?(file) ? Telegram::Bot::Types::InputMediaPhoto : Telegram::Bot::Types::InputMediaDocument
178
+ end
179
+
180
+ def photo?(file)
181
+ PHOTO_EXTENSIONS.include?(File.extname(file.is_a?(String) ? file : file.path).downcase)
128
182
  end
129
183
  end
data/telepost.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=)
10
10
  s.required_ruby_version = '>=3.2'
11
11
  s.name = 'telepost'
12
- s.version = '0.8.1'
12
+ s.version = '0.9.0'
13
13
  s.license = 'MIT'
14
14
  s.summary = 'Simple Telegram posting Ruby gem'
15
15
  s.description = 'Simple Telegram posting Ruby gem'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: telepost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko