diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25e54622..72438d23 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,6 +41,7 @@ jobs: parallel: true github-token: ${{ secrets.GITHUB_TOKEN }} flag-name: run-${{ matrix.entry.ruby }}${{ matrix.entry.concurrency && '-'}}${{ matrix.entry.concurrency }} + allow-empty: ${{ matrix.entry.ignore || false }} finish: name: coveralls diff --git a/CHANGELOG.md b/CHANGELOG.md index 855155cc..33913754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * [#549](https://github.com/slack-ruby/slack-ruby-client/pull/549): Add group ID formatting support for message mentions - [@n0h0](https://github.com/n0h0). * [#553](https://github.com/slack-ruby/slack-ruby-client/pull/553): Use `secure_compare` during signature verification - [@hieuk09](https://github.com/hieuk09). +* [#555](https://github.com/slack-ruby/slack-ruby-client/pull/555): Make page size in resolving IDs configurable - [@eizengan](https://github.com/eizengan). * Your contribution here. ### 2.5.2 (2025/02/19) diff --git a/README.md b/README.md index 2b705aa1..7a24519b 100644 --- a/README.md +++ b/README.md @@ -179,7 +179,7 @@ client.files_upload_v2( # required options filename: 'results.pdf', # this is used for the file title, unless a :title option is provided content: File.read('/users/me/results.pdf'), # the string contents of the file - + # optional options channels: ['C000000', 'C000001'], # channel IDs to share the file in (:channel_id, :channel, or :channels are all supported) initial_comment: 'Sharing the Q1 results :tada:', # the message that is included with the file share thread @@ -281,20 +281,22 @@ client = Slack::Web::Client.new(user_agent: 'Slack Ruby Client/1.0') The following settings are supported. -setting | description ---------------------|------------------------------------------------------------------------------------------------- -token | Slack API token. -user_agent | User-agent, defaults to _Slack Ruby Client/version_. -proxy | Optional HTTP proxy. -ca_path | Optional SSL certificates path. -ca_file | Optional SSL certificates file. -endpoint | Slack endpoint, default is _https://slack.com/api_. -logger | Optional `Logger` instance that logs HTTP requests. -timeout | Optional open/read timeout in seconds. -open_timeout | Optional connection open timeout in seconds. -default_page_size | Optional page size for paginated requests, default is _100_. -default_max_retries | Optional number of retries for paginated requests, default is _100_. -adapter | Optional HTTP adapter to use, defaults to `Faraday.default_adapter`. +setting | description +-----------------------------|------------------------------------------------------------------------------------------------- +token | Slack API token. +user_agent | User-agent, defaults to _Slack Ruby Client/version_. +proxy | Optional HTTP proxy. +ca_path | Optional SSL certificates path. +ca_file | Optional SSL certificates file. +endpoint | Slack endpoint, default is _https://slack.com/api_. +logger | Optional `Logger` instance that logs HTTP requests. +timeout | Optional open/read timeout in seconds. +open_timeout | Optional connection open timeout in seconds. +default_page_size | Optional page size for paginated requests, default is _100_. +conversations_id_page_size | Optional page size for conversations_list requests made when calculating conversation id from a conversation name, default is _nil_, which will use the default_page_size. +users_id_page_size | Optional page size for users_list requests made when calculating user id from a user name, default is _nil_, which will use the default_page_size. +default_max_retries | Optional number of retries for paginated requests, default is _100_. +adapter | Optional HTTP adapter to use, defaults to `Faraday.default_adapter`. You can also pass request options, including `timeout` and `open_timeout` into individual calls. diff --git a/lib/slack/web/api/mixins/conversations.id.rb b/lib/slack/web/api/mixins/conversations.id.rb index b3b51cb0..51789c84 100644 --- a/lib/slack/web/api/mixins/conversations.id.rb +++ b/lib/slack/web/api/mixins/conversations.id.rb @@ -12,11 +12,22 @@ module Conversations # # @option options [channel] :channel # Channel to get ID for, prefixed with #. + # @option options [integer] :id_limit + # The page size used for conversations_list calls required to find the channel's ID def conversations_id(options = {}) name = options[:channel] + limit = options.fetch(:id_limit, Slack::Web.config.conversations_id_page_size) + raise ArgumentError, 'Required arguments :channel missing' if name.nil? - id_for :channel, name, '#', :conversations_list, :channels, 'channel_not_found' + id_for( + key: :channel, + name: name, + prefix: '#', + enum_method: :conversations_list, + list_method: :channels, + options: { limit: limit }.compact + ) end end end diff --git a/lib/slack/web/api/mixins/ids.id.rb b/lib/slack/web/api/mixins/ids.id.rb index 50c2a495..40f8dd1d 100644 --- a/lib/slack/web/api/mixins/ids.id.rb +++ b/lib/slack/web/api/mixins/ids.id.rb @@ -6,16 +6,16 @@ module Mixins module Ids private - def id_for(key, name, prefix, enum_method, list_method, not_found_error) + def id_for(key:, name:, prefix:, enum_method:, list_method:, options: {}) return { 'ok' => true, key.to_s => { 'id' => name } } unless name[0] == prefix - public_send enum_method do |list| + public_send(enum_method, **options) do |list| list.public_send(list_method).each do |li| return Slack::Messages::Message.new('ok' => true, key.to_s => { 'id' => li.id }) if li.name == name[1..-1] end end - raise Slack::Web::Api::Errors::SlackError, not_found_error + raise Slack::Web::Api::Errors::SlackError, "#{key}_not_found" end end end diff --git a/lib/slack/web/api/mixins/users.id.rb b/lib/slack/web/api/mixins/users.id.rb index 15aaa36b..94fc98a1 100644 --- a/lib/slack/web/api/mixins/users.id.rb +++ b/lib/slack/web/api/mixins/users.id.rb @@ -12,11 +12,22 @@ module Users # # @option options [user] :user # User to get ID for, prefixed with '@'. + # @option options [integer] :id_limit + # The page size used for users_list calls required to find the user's ID def users_id(options = {}) name = options[:user] + limit = options.fetch(:id_limit, Slack::Web.config.users_id_page_size) + raise ArgumentError, 'Required arguments :user missing' if name.nil? - id_for :user, name, '@', :users_list, :members, 'user_not_found' + id_for( + key: :user, + name: name, + prefix: '@', + enum_method: :users_list, + list_method: :members, + options: { limit: limit }.compact + ) end end end diff --git a/lib/slack/web/config.rb b/lib/slack/web/config.rb index 3c460d5e..ef8052ba 100644 --- a/lib/slack/web/config.rb +++ b/lib/slack/web/config.rb @@ -15,6 +15,8 @@ module Config timeout open_timeout default_page_size + conversations_id_page_size + users_id_page_size default_max_retries adapter ].freeze @@ -32,6 +34,8 @@ def reset self.timeout = nil self.open_timeout = nil self.default_page_size = 100 + self.conversations_id_page_size = nil + self.users_id_page_size = nil self.default_max_retries = 100 self.adapter = ::Faraday.default_adapter end diff --git a/spec/slack/web/api/mixins/conversations_spec.rb b/spec/slack/web/api/mixins/conversations_spec.rb index 4bdac52a..56cd270e 100644 --- a/spec/slack/web/api/mixins/conversations_spec.rb +++ b/spec/slack/web/api/mixins/conversations_spec.rb @@ -31,15 +31,39 @@ end it 'translates a channel that starts with a #' do + expect(conversations).to receive(:conversations_list) expect(conversations.conversations_id(channel: '#general')).to( eq('ok' => true, 'channel' => { 'id' => 'CDEADBEEF' }) ) end + it 'forwards a provided limit to the underlying conversations_list calls' do + expect(conversations).to receive(:conversations_list).with(limit: 1234) + conversations.conversations_id(channel: '#general', id_limit: 1234) + end + it 'fails with an exception' do expect { conversations.conversations_id(channel: '#invalid') }.to( raise_error(Slack::Web::Api::Errors::SlackError, 'channel_not_found') ) end + + context 'when a non-default conversations_id page size has been configured' do + before { Slack::Web.config.conversations_id_page_size = 500 } + + after { Slack::Web.config.reset } + + it 'translates a channel that starts with a #' do + expect(conversations).to receive(:conversations_list).with(limit: 500) + expect(conversations.conversations_id(channel: '#general')).to( + eq('ok' => true, 'channel' => { 'id' => 'CDEADBEEF' }) + ) + end + + it 'forwards a provided limit to the underlying conversations_list calls' do + expect(conversations).to receive(:conversations_list).with(limit: 1234) + conversations.conversations_id(channel: '#general', id_limit: 1234) + end + end end end diff --git a/spec/slack/web/api/mixins/users_spec.rb b/spec/slack/web/api/mixins/users_spec.rb index 5ee3063d..054d791a 100644 --- a/spec/slack/web/api/mixins/users_spec.rb +++ b/spec/slack/web/api/mixins/users_spec.rb @@ -30,14 +30,36 @@ end it 'translates a user that starts with a @' do + expect(users).to receive(:users_list) expect(users.users_id(user: '@aws')).to eq('ok' => true, 'user' => { 'id' => 'UDEADBEEF' }) end + it 'forwards a provided limit to the underlying users_list calls' do + expect(users).to receive(:users_list).with(limit: 1234) + users.users_id(user: '@aws', id_limit: 1234) + end + it 'fails with an exception' do expect { users.users_id(user: '@foo') }.to( raise_error(Slack::Web::Api::Errors::SlackError, 'user_not_found') ) end + + context 'when a non-default conversations_id page size has been configured' do + before { Slack::Web.config.users_id_page_size = 500 } + + after { Slack::Web.config.reset } + + it 'translates a user that starts with a @' do + expect(users).to receive(:users_list).with(limit: 500) + expect(users.users_id(user: '@aws')).to eq('ok' => true, 'user' => { 'id' => 'UDEADBEEF' }) + end + + it 'forwards a provided limit to the underlying users_list calls' do + expect(users).to receive(:users_list).with(limit: 1234) + users.users_id(user: '@aws', id_limit: 1234) + end + end end if defined?(Picky)