Skip to content

Commit 3a2277a

Browse files
authored
Added files_upload_external (#533)
1 parent c75d8e4 commit 3a2277a

File tree

15 files changed

+911
-35
lines changed

15 files changed

+911
-35
lines changed

.rubocop_todo.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2024-11-06 16:01:45 UTC using RuboCop version 1.26.1.
3+
# on 2025-02-04 16:47:31 UTC using RuboCop version 1.26.1.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -44,17 +44,17 @@ Lint/RedundantCopDisableDirective:
4444
Exclude:
4545
- 'lib/slack-ruby-client.rb'
4646

47-
# Offense count: 12
47+
# Offense count: 13
4848
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
4949
Metrics/AbcSize:
50-
Max: 36
50+
Max: 34
5151

52-
# Offense count: 4
52+
# Offense count: 5
5353
# Configuration parameters: IgnoredMethods.
5454
Metrics/CyclomaticComplexity:
55-
Max: 10
55+
Max: 9
5656

57-
# Offense count: 13
57+
# Offense count: 15
5858
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
5959
Metrics/MethodLength:
6060
Max: 26
@@ -67,7 +67,7 @@ Metrics/ParameterLists:
6767
# Offense count: 2
6868
# Configuration parameters: IgnoredMethods.
6969
Metrics/PerceivedComplexity:
70-
Max: 10
70+
Max: 9
7171

7272
# Offense count: 2
7373
# This cop supports safe auto-correction (--auto-correct).
@@ -94,12 +94,12 @@ RSpec/ContextMethod:
9494
RSpec/ContextWording:
9595
Enabled: false
9696

97-
# Offense count: 65
97+
# Offense count: 67
9898
# Configuration parameters: CountAsOne.
9999
RSpec/ExampleLength:
100100
Max: 18
101101

102-
# Offense count: 18
102+
# Offense count: 19
103103
# Configuration parameters: Include, CustomTransform, IgnoreMethods, SpecSuffixOnly.
104104
# Include: **/*_spec*rb*, **/spec/**/*
105105
RSpec/FilePath:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* [#527](https://github.com/slack-ruby/slack-ruby-client/pull/527): Explicitly require `racc` and `ostruct` - [@dblock](https://github.com/dblock).
55
* [#528](https://github.com/slack-ruby/slack-ruby-client/pull/528): Don't treat asterisks in list items as italic in markdown - [@rspeicher](https://github.com/rspeicher).
66
* [#530](https://github.com/slack-ruby/slack-ruby-client/pull/530): Specify dependency on logger - [@rwstauner](https://github.com/rwstauner).
7+
* [#533](https://github.com/slack-ruby/slack-ruby-client/pull/533): Added `files_upload_external` - [@gregsaab](https://github.com/gregsaab).
78
* Your contribution here.
89

910
### 2.4.0 (2024/07/14)

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,25 @@ general_channel = channels.detect { |c| c.name == 'general' }
171171

172172
##### Upload a File
173173

174-
Upload a file with [files_upload](https://api.slack.com/methods/files.upload).
174+
Upload files with [sequenced API calls](https://api.slack.com/messaging/files#uploading_files).
175+
176+
This library provides a helper method `files_upload_external` that wraps the three separate API calls.
177+
178+
```ruby
179+
client.files_upload_external(
180+
# required options
181+
channels: 'C000000,C000001', # comma delimited channel ids, only one channel is required
182+
filename: 'results.pdf', # this is used for the file title, unless a :title option is provided
183+
contents: File.read('/users/me/results.pdf'), # the string contents of the file
184+
185+
# optional options
186+
initial_comment: 'Sharing the Q1 results :tada:', # the message that is included with the file share thread
187+
snippet_type: 'text', # the type of snippet
188+
title: 'Q1 Results', # sets the title of the file, overriding the filename
189+
thread_ts: '1738331487.481469' # specifies a thread to add this file to
190+
)
191+
```
192+
Note: This library includes a `files_upload` method that uses a deprecated endpoint `files.upload` that will [no longer be supported on 3/11/2025](https://api.slack.com/methods/files.upload#markdown).
175193

176194
```ruby
177195
client.files_upload(

lib/slack-ruby-client.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@
3333
require_relative 'slack/web/api/options'
3434
require_relative 'slack/web/faraday/response/raise_error'
3535
require_relative 'slack/web/faraday/response/wrap_error'
36+
require_relative 'slack/web/faraday/connection_options'
3637
require_relative 'slack/web/faraday/connection'
38+
require_relative 'slack/web/faraday/plain_text_connection'
3739
require_relative 'slack/web/faraday/request'
3840
require_relative 'slack/web/api/mixins'
3941
require_relative 'slack/web/api/endpoints'
42+
require_relative 'slack/web/api/helpers'
4043
require_relative 'slack/web/pagination/cursor'
4144
require_relative 'slack/web/client'
4245

lib/slack/web/api/helpers.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# frozen_string_literal: true
2+
3+
require_relative 'helpers/files'
4+
5+
module Slack
6+
module Web
7+
module Api
8+
module Helpers
9+
include Files
10+
end
11+
end
12+
end
13+
end

lib/slack/web/api/helpers/files.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
module Slack
3+
module Web
4+
module Api
5+
module Helpers
6+
module Files
7+
#
8+
# Uses Slack APIs new sequential file upload flow. This replaces the files.upload method
9+
# @see https://api.slack.com/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay
10+
# @see https://api.slack.com/messaging/files#uploading_files
11+
#
12+
# @option options [string] :filename
13+
# Name of the file being uploaded.
14+
# @option options [string] :content
15+
# File contents via a POST variable.
16+
# @option options [string] :alt_txt
17+
# Description of image for screen-reader.
18+
# @option options [string] :snippet_type
19+
# Syntax type of the snippet being uploaded.
20+
# @option options [string] :title
21+
# Title of file.
22+
# @option options [string] :channels
23+
# Comma-separated string of channel IDs where the file will be shared. If not specified the file will be private.
24+
# @option options [string] :initial_comment
25+
# The message text introducing the file in specified channels.
26+
# @option options [string] :thread_ts
27+
# Provide another message's ts value to upload this file as a reply.
28+
# Never use a reply's ts value; use its parent instead.
29+
# Also make sure to provide only one channel when using 'thread_ts'.
30+
def files_upload_external(options = {})
31+
%i[filename content channels].each do |param|
32+
raise ArgumentError, "Required argument :#{param} missing" if options[param].nil?
33+
end
34+
35+
content = options[:content]
36+
title = options[:title] || options[:filename]
37+
38+
upload_url_request_params = options.slice(:filename, :alt_txt, :snippet_type)
39+
upload_url_request_params[:length] = content.bytesize
40+
41+
# Get the upload url.
42+
get_upload_url_response = files_getUploadURLExternal(upload_url_request_params)
43+
upload_url = get_upload_url_response[:upload_url]
44+
file_id = get_upload_url_response[:file_id]
45+
46+
# Upload the file.
47+
plain_text_connection.post do |request|
48+
request.url upload_url
49+
request.body = content
50+
end
51+
52+
# Complete the upload.
53+
complete_upload_request_params = options.slice(:channels, :initial_comment, :thread_ts)
54+
complete_upload_request_params[:files] = [{ id: file_id, title: title }].to_json
55+
56+
files_completeUploadExternal(complete_upload_request_params)
57+
end
58+
end
59+
end
60+
end
61+
end
62+
end

lib/slack/web/client.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ module Slack
33
module Web
44
class Client
55
include Faraday::Connection
6+
include Faraday::PlainTextConnection
67
include Faraday::Request
78
include Api::Endpoints
9+
include Api::Helpers
810
include Api::Options
911

1012
attr_accessor(*Config::ATTRIBUTES)

lib/slack/web/faraday/connection.rb

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,29 @@ module Slack
33
module Web
44
module Faraday
55
module Connection
6+
include ConnectionOptions
7+
68
private
79

10+
def options
11+
@options ||= begin
12+
options = connection_options.dup
13+
options[:headers]['Accept'] = 'application/json; charset=utf-8'
14+
options
15+
end
16+
end
17+
818
def connection
919
@connection ||=
10-
begin
11-
options = {
12-
headers: { 'Accept' => 'application/json; charset=utf-8' }
13-
}
14-
15-
options[:headers]['User-Agent'] = user_agent if user_agent
16-
options[:proxy] = proxy if proxy
17-
options[:ssl] = { ca_path: ca_path, ca_file: ca_file } if ca_path || ca_file
18-
19-
request_options = {}
20-
request_options[:timeout] = timeout if timeout
21-
request_options[:open_timeout] = open_timeout if open_timeout
22-
options[:request] = request_options if request_options.any?
23-
24-
::Faraday::Connection.new(endpoint, options) do |connection|
25-
connection.request :multipart
26-
connection.request :url_encoded
27-
connection.use ::Slack::Web::Faraday::Response::RaiseError
28-
connection.response :mashify, mash_class: Slack::Messages::Message
29-
connection.response :json, content_type: /\b*$/
30-
connection.use ::Slack::Web::Faraday::Response::WrapError
31-
connection.response :logger, logger if logger
32-
connection.adapter adapter
33-
end
20+
::Faraday::Connection.new(endpoint, options) do |connection|
21+
connection.request :multipart
22+
connection.request :url_encoded
23+
connection.use ::Slack::Web::Faraday::Response::RaiseError
24+
connection.response :mashify, mash_class: Slack::Messages::Message
25+
connection.response :json, content_type: /\b*$/
26+
connection.use ::Slack::Web::Faraday::Response::WrapError
27+
connection.response :logger, logger if logger
28+
connection.adapter adapter
3429
end
3530
end
3631
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
module Slack
3+
module Web
4+
module Faraday
5+
module ConnectionOptions
6+
def connection_options
7+
@connection_options ||= begin
8+
options = { headers: {} }
9+
options[:headers]['User-Agent'] = user_agent if user_agent
10+
options[:proxy] = proxy if proxy
11+
options[:ssl] = { ca_path: ca_path, ca_file: ca_file } if ca_path || ca_file
12+
13+
request_options = {}
14+
request_options[:timeout] = timeout if timeout
15+
request_options[:open_timeout] = open_timeout if open_timeout
16+
options[:request] = request_options if request_options.any?
17+
18+
options
19+
end
20+
end
21+
end
22+
end
23+
end
24+
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
module Slack
3+
module Web
4+
module Faraday
5+
module PlainTextConnection
6+
include ConnectionOptions
7+
8+
private
9+
10+
def plain_text_connection
11+
@plain_text_connection ||=
12+
::Faraday::Connection.new(endpoint, connection_options) do |connection|
13+
connection.request :multipart
14+
connection.request :url_encoded
15+
connection.use ::Slack::Web::Faraday::Response::WrapError
16+
connection.response :logger, logger if logger
17+
connection.adapter adapter
18+
end
19+
end
20+
end
21+
end
22+
end
23+
end

0 commit comments

Comments
 (0)