diff --git a/README.md b/README.md index 1ad4fde..54c24f8 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,9 @@ client.user_by_username("username") #=> # #Twttr::Client#users(:user_ids) client.users(["user_id_1", "user_id_2"]) #=> [#] + +# Twttr::Client#Following +client.following("user_id") == client.user("user_id").following ``` ### User ```ruby @@ -51,8 +54,8 @@ client.users(["user_id_1", "user_id_2"]) #=> [#] # Yields each page of users user.following do |users, pagination_token| users #=> [#] -end +end #=> [#] # First page of users -user.following #=> [#], pagination_token +user.following #=> [#] ``` diff --git a/lib/twttr/client/endpoint/v2/users.rb b/lib/twttr/client/endpoint/v2/users.rb index 41f1651..d3aeed4 100644 --- a/lib/twttr/client/endpoint/v2/users.rb +++ b/lib/twttr/client/endpoint/v2/users.rb @@ -12,23 +12,62 @@ module Users USER_BY_USERNAME_PATH = "#{V2::V2_PATH}/users/by/username/%s" USER_PATH = "#{V2::V2_PATH}/users/%s" + # GET /2/users/:id/following + # https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following + # + # Returns paginated list of users followed by user_id. + # + # @param user_id [String] The user ID whose following you would like to retrieve. + # @param max_results [Integer] Max number of results per peage. + # @param pagination_token [String] Initial page pagination token. + # @yield [Array] Users followed by page. + # @yield [String,NilClass] Pagination token. + # @return [Array] Users followed. + + # GET /2/users/me + # https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me + # + # Returns current authenticated user + # + # @return [Twttr::Model::User] Current user. def me response = get(ME_PATH, query_params: { 'user.fields': config.user_fields }) Model::User.new(response['data'], self) end + # GET /2/users/:id + # https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-id + # + # Returns target user by id + # + # @param user_id [String] Traget user id. + # @return [Twttr::Model::User] Target user. def user(user_id) response = get(USER_PATH, params: { user_id: user_id }, query_params: { 'user.fields': config.user_fields }) Model::User.new(response['data'], self) end + # GET /2/users/by/username/:username + # https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-by-username-username + # + # Returns target user by username + # + # @param username [String] Traget username. + # @return [Twttr::Model::User] Target user. def user_by_username(username) response = get(USER_BY_USERNAME_PATH, params: { username: username }, query_params: { 'user.fields': config.user_fields }) Model::User.new(response['data'], self) end + # GET /2/users + # https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users + # + # Returns target users by id + # + # @param user_ids [Array] Traget user ids. + # @return [Array] Target users. def users(user_ids) response = get(USERS_PATH, query_params: { ids: user_ids.join(','), 'user.fields': config.user_fields }) diff --git a/lib/twttr/client/endpoint/v2/users/follows.rb b/lib/twttr/client/endpoint/v2/users/follows.rb index e9232f0..eae4c4e 100644 --- a/lib/twttr/client/endpoint/v2/users/follows.rb +++ b/lib/twttr/client/endpoint/v2/users/follows.rb @@ -13,13 +13,15 @@ module Follows # GET /2/users/:id/following # https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following # + # Returns paginated list of users followed by user_id. + # # @param user_id [String] The user ID whose following you would like to retrieve. # @param max_results [Integer] Max number of results per peage. # @param pagination_token [String] Initial page pagination token. # @yield [Array] Users followed by page. + # @yield [String,NilClass] Pagination token. # @return [Array] Users followed. - # @return [String,NilClass] Pagination token. - def following(user_id, max_results: nil, pagination_token: nil, &block) # rubocop:disable Metrics/MethodLength + def following(user_id, max_results: nil, pagination_token: nil, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize response = get(FOLLOWING_PATH, params: { user_id: user_id }, query_params: { 'user.fields': config.user_fields, @@ -33,11 +35,11 @@ def following(user_id, max_results: nil, pagination_token: nil, &block) # ruboco pagination_token = response['meta']['pagination_token'] - return users, pagination_token unless block_given? + yield users, pagination_token if block_given? - yield users, pagination_token + return users if pagination_token.nil? - following(user_id, pagination_token, &block) unless pagination_token.nil? + users + following(user_id, pagination_token: pagination_token, &block) end end end diff --git a/lib/twttr/model/user.rb b/lib/twttr/model/user.rb index f58883c..0faa8cd 100644 --- a/lib/twttr/model/user.rb +++ b/lib/twttr/model/user.rb @@ -15,6 +15,18 @@ def initialize(data, client = nil) @client = client end + # Forwards to Follows#following setting user_id to current user's id. + # + # GET /2/users/:id/following + # https://developer.twitter.com/en/docs/twitter-api/users/follows/api-reference/get-users-id-following + # + # Returns paginated list of users followed by user_id. + # + # @param max_results [Integer] Max number of results per peage. + # @param pagination_token [String] Initial page pagination token. + # @yield [Array] Users followed by page. + # @yield [String,NilClass] Pagination token. + # @return [Array] Users followed. def following(max_results: nil, pagination_token: nil, &block) client.following(id, max_results: max_results, pagination_token: pagination_token, &block) end diff --git a/test/lib/twttr/client/endpoint/v2/users/test_follows.rb b/test/lib/twttr/client/endpoint/v2/users/test_follows.rb index 35344d6..f46b627 100644 --- a/test/lib/twttr/client/endpoint/v2/users/test_follows.rb +++ b/test/lib/twttr/client/endpoint/v2/users/test_follows.rb @@ -17,40 +17,49 @@ def setup config.access_token_secret = 'access_secret' end - mock_body = '{ + first_mock_body = '{ "data": [ {"id": "1234", "username": "@username"}, {"id": "12345", "username": "@username2"} ], + "meta": {"result_count": 2, "pagination_token": "next-token"} + }' + second_mock_body = '{ + "data": [ + {"id": "123456", "username": "@username3"}, + {"id": "1234567", "username": "@username4"} + ], "meta": {"result_count": 2} }' - @mock_oauth_response = OpenStruct.new(body: mock_body) + @mock_oauth_responses = { + 'https://api.twitter.com/2/users/user_id/following' => OpenStruct.new(body: first_mock_body), + 'https://api.twitter.com/2/users/user_id/following?pagination_token=next-token' => OpenStruct.new(body: second_mock_body) + } end def test_following mock = lambda do |uri, _config| - assert_equal('https://api.twitter.com/2/users/user_id/following', uri.to_s) - @mock_oauth_response + @mock_oauth_responses[uri.to_s] end Twttr::Client::OAuthRequest.stub :get, mock do - users, token = @client.following('user_id') - assert_equal(2, users.length) + users = @client.following('user_id') + assert_equal(4, users.length) users.each { |user| assert_instance_of(Twttr::Model::User, user) } - assert_nil(token) end end def test_following_with_block mock = lambda do |uri, _config| - assert_equal('https://api.twitter.com/2/users/user_id/following', uri.to_s) - @mock_oauth_response + @mock_oauth_responses[uri.to_s] end Twttr::Client::OAuthRequest.stub :get, mock do - @client.following('user_id') do |users, token| + all_users = @client.following('user_id') do |users, token| assert_equal(2, users.length) users.each { |user| assert_instance_of(Twttr::Model::User, user) } assert_nil(nil, token) end + assert_equal(4, all_users.length) + all_users.each { |user| assert_instance_of(Twttr::Model::User, user) } end end diff --git a/test/lib/twttr/model/test_user.rb b/test/lib/twttr/model/test_user.rb index 0eb3a81..d859f7d 100644 --- a/test/lib/twttr/model/test_user.rb +++ b/test/lib/twttr/model/test_user.rb @@ -15,14 +15,24 @@ def setup end @user = Twttr::Model::User.new({ id: 'user_id' }, @client) - mock_body = '{ + first_mock_body = '{ "data": [ {"id": "1234", "username": "@username"}, {"id": "12345", "username": "@username2"} ], + "meta": {"result_count": 2, "pagination_token": "next-token"} + }' + second_mock_body = '{ + "data": [ + {"id": "123456", "username": "@username3"}, + {"id": "1234567", "username": "@username4"} + ], "meta": {"result_count": 2} }' - @mock_oauth_response = OpenStruct.new(body: mock_body) + @mock_oauth_responses = { + 'https://api.twitter.com/2/users/user_id/following' => OpenStruct.new(body: first_mock_body), + 'https://api.twitter.com/2/users/user_id/following?pagination_token=next-token' => OpenStruct.new(body: second_mock_body) + } end def test_initialize @@ -56,28 +66,28 @@ def test_initialize def test_following mock = lambda do |uri, _config| - assert_equal('https://api.twitter.com/2/users/user_id/following', uri.to_s) - @mock_oauth_response + @mock_oauth_responses[uri.to_s] end Twttr::Client::OAuthRequest.stub :get, mock do - users, token = @user.following - assert_equal(2, users.length) + users = @user.following + assert_equal(4, users.length) users.each { |user| assert_instance_of(Twttr::Model::User, user) } - assert_nil(token) end end - def test_following_with_block + def test_following_with_block # rubocop:disable Metrics/AbcSize mock = lambda do |uri, _config| - assert_equal('https://api.twitter.com/2/users/user_id/following', uri.to_s) - @mock_oauth_response + puts uri.to_s + @mock_oauth_responses[uri.to_s] end Twttr::Client::OAuthRequest.stub :get, mock do - @user.following do |users, token| + all_users = @user.following do |users, token| assert_equal(2, users.length) users.each { |user| assert_instance_of(Twttr::Model::User, user) } assert_nil(nil, token) end + assert_equal(4, all_users.length) + all_users.each { |user| assert_instance_of(Twttr::Model::User, user) } end end end diff --git a/twttr.gemspec b/twttr.gemspec index 979b8f4..e146d27 100644 --- a/twttr.gemspec +++ b/twttr.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.name = 'twttr' - s.version = '0.0.3' + s.version = '0.0.4' s.summary = 'Twitter API v2 Interface' s.description = 'Modular Twitter API interface, initially targeting Twitter API v2' s.authors = ['Roberto Decurnex']