pinterest-ruby 1.0.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 (150) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rubocop.yml +63 -0
  4. data/.travis-gemfile +17 -0
  5. data/.travis.yml +12 -0
  6. data/.yardopts +1 -0
  7. data/CHANGELOG.md +3 -0
  8. data/Gemfile +24 -0
  9. data/README.md +34 -0
  10. data/Rakefile +44 -0
  11. data/docs/FaradayMiddleware/SafeOj.html +218 -0
  12. data/docs/FaradayMiddleware.html +125 -0
  13. data/docs/Pinterest/Board.html +410 -0
  14. data/docs/Pinterest/Client.html +1894 -0
  15. data/docs/Pinterest/Collection.html +1877 -0
  16. data/docs/Pinterest/Endpoints/Authentication.html +578 -0
  17. data/docs/Pinterest/Endpoints/Boards.html +1443 -0
  18. data/docs/Pinterest/Endpoints/Pins.html +1296 -0
  19. data/docs/Pinterest/Endpoints/Users.html +1220 -0
  20. data/docs/Pinterest/Endpoints.html +127 -0
  21. data/docs/Pinterest/Entity.html +473 -0
  22. data/docs/Pinterest/Errors/AuthorizationError.html +158 -0
  23. data/docs/Pinterest/Errors/BadRequestError.html +158 -0
  24. data/docs/Pinterest/Errors/BaseError.html +487 -0
  25. data/docs/Pinterest/Errors/MethodNotAllowedError.html +158 -0
  26. data/docs/Pinterest/Errors/NotFoundError.html +158 -0
  27. data/docs/Pinterest/Errors/NotImplementedError.html +158 -0
  28. data/docs/Pinterest/Errors/PermissionsError.html +158 -0
  29. data/docs/Pinterest/Errors/RateLimitError.html +158 -0
  30. data/docs/Pinterest/Errors/ServerError.html +158 -0
  31. data/docs/Pinterest/Errors/TimeoutError.html +158 -0
  32. data/docs/Pinterest/Errors.html +377 -0
  33. data/docs/Pinterest/Image.html +617 -0
  34. data/docs/Pinterest/Interest.html +402 -0
  35. data/docs/Pinterest/Pin.html +511 -0
  36. data/docs/Pinterest/User.html +408 -0
  37. data/docs/Pinterest/Version.html +187 -0
  38. data/docs/Pinterest.html +130 -0
  39. data/docs/_index.html +401 -0
  40. data/docs/class_list.html +51 -0
  41. data/docs/css/common.css +1 -0
  42. data/docs/css/full_list.css +58 -0
  43. data/docs/css/style.css +492 -0
  44. data/docs/file.README.html +106 -0
  45. data/docs/file_list.html +56 -0
  46. data/docs/frames.html +17 -0
  47. data/docs/index.html +106 -0
  48. data/docs/js/app.js +243 -0
  49. data/docs/js/full_list.js +216 -0
  50. data/docs/js/jquery.js +4 -0
  51. data/docs/method_list.html +643 -0
  52. data/docs/top-level-namespace.html +110 -0
  53. data/lib/pinterest/client.rb +146 -0
  54. data/lib/pinterest/collection.rb +97 -0
  55. data/lib/pinterest/endpoints/authentication.rb +99 -0
  56. data/lib/pinterest/endpoints/boards.rb +193 -0
  57. data/lib/pinterest/endpoints/pins.rb +187 -0
  58. data/lib/pinterest/endpoints/users.rb +158 -0
  59. data/lib/pinterest/errors.rb +94 -0
  60. data/lib/pinterest/models/board.rb +34 -0
  61. data/lib/pinterest/models/entity.rb +42 -0
  62. data/lib/pinterest/models/image.rb +49 -0
  63. data/lib/pinterest/models/interest.rb +30 -0
  64. data/lib/pinterest/models/pin.rb +43 -0
  65. data/lib/pinterest/models/user.rb +33 -0
  66. data/lib/pinterest/safe_oj.rb +25 -0
  67. data/lib/pinterest/version.rb +23 -0
  68. data/lib/pinterest.rb +31 -0
  69. data/pinterest.gemspec +32 -0
  70. data/spec/cassettes/Pinterest_Client/_perform_network_request_private_/should_correctly_handle_malformed_requests.yml +51 -0
  71. data/spec/cassettes/Pinterest_Endpoints_Authentication/_fetch_access_token/should_make_the_call_to_Pinterest_and_return_the_authorization_token_also_saving_it.yml +58 -0
  72. data/spec/cassettes/Pinterest_Endpoints_Authentication/_verify_access_token/should_return_an_exception_when_using_an_invalid_token.yml +52 -0
  73. data/spec/cassettes/Pinterest_Endpoints_Authentication/_verify_access_token/should_verify_the_token.yml +59 -0
  74. data/spec/cassettes/Pinterest_Endpoints_Boards/_board/should_complain_for_invalid_boards.yml +48 -0
  75. data/spec/cassettes/Pinterest_Endpoints_Boards/_board/should_get_the_current_informations.yml +63 -0
  76. data/spec/cassettes/Pinterest_Endpoints_Boards/_board/should_restrict_to_requested_fields.yml +57 -0
  77. data/spec/cassettes/Pinterest_Endpoints_Boards/_boards/should_only_get_requested_fields.yml +57 -0
  78. data/spec/cassettes/Pinterest_Endpoints_Boards/_boards/should_return_a_list_of_boards.yml +74 -0
  79. data/spec/cassettes/Pinterest_Endpoints_Boards/_create_board/should_create_the_board_and_return_it_with_only_the_requested_fields.yml +56 -0
  80. data/spec/cassettes/Pinterest_Endpoints_Boards/_delete_board/should_perform_the_call_and_return_an_error.yml +48 -0
  81. data/spec/cassettes/Pinterest_Endpoints_Boards/_delete_board/should_perform_the_call_and_return_true.yml +109 -0
  82. data/spec/cassettes/Pinterest_Endpoints_Boards/_edit_board/should_edit_the_board_and_return_it_with_only_the_requested_fields.yml +56 -0
  83. data/spec/cassettes/Pinterest_Endpoints_Boards/_follow_board/should_complain_for_invalid_boards.yml +56 -0
  84. data/spec/cassettes/Pinterest_Endpoints_Boards/_follow_board/should_perform_the_call_and_return_true.yml +109 -0
  85. data/spec/cassettes/Pinterest_Endpoints_Boards/_following_boards/should_only_get_requested_fields.yml +59 -0
  86. data/spec/cassettes/Pinterest_Endpoints_Boards/_following_boards/should_paginate_correctly.yml +72 -0
  87. data/spec/cassettes/Pinterest_Endpoints_Boards/_following_boards/should_return_the_followed_boards.yml +72 -0
  88. data/spec/cassettes/Pinterest_Endpoints_Boards/_search_my_boards/should_only_get_requested_fields.yml +59 -0
  89. data/spec/cassettes/Pinterest_Endpoints_Boards/_search_my_boards/should_paginate_correctly.yml +66 -0
  90. data/spec/cassettes/Pinterest_Endpoints_Boards/_search_my_boards/should_search_boards.yml +75 -0
  91. data/spec/cassettes/Pinterest_Endpoints_Boards/_suggested_boards/should_return_the_suggested_boards_returning_only_the_requested_fields.yml +56 -0
  92. data/spec/cassettes/Pinterest_Endpoints_Boards/_unfollow_board/should_complain_for_invalid_boards.yml +56 -0
  93. data/spec/cassettes/Pinterest_Endpoints_Boards/_unfollow_board/should_perform_the_call_and_return_true.yml +109 -0
  94. data/spec/cassettes/Pinterest_Endpoints_Pins/_board_pins/should_only_get_requested_fields.yml +59 -0
  95. data/spec/cassettes/Pinterest_Endpoints_Pins/_board_pins/should_paginate_correctly.yml +85 -0
  96. data/spec/cassettes/Pinterest_Endpoints_Pins/_board_pins/should_return_the_pins_of_the_board.yml +85 -0
  97. data/spec/cassettes/Pinterest_Endpoints_Pins/_create_pin/should_create_a_pin_by_using_a_image_URL.yml +71 -0
  98. data/spec/cassettes/Pinterest_Endpoints_Pins/_create_pin/should_create_a_pin_by_using_a_image_file.yml +1997 -0
  99. data/spec/cassettes/Pinterest_Endpoints_Pins/_create_pin/should_return_a_pin_containing_only_requested_fields.yml +56 -0
  100. data/spec/cassettes/Pinterest_Endpoints_Pins/_delete_pin/should_perform_the_call_and_return_an_error.yml +56 -0
  101. data/spec/cassettes/Pinterest_Endpoints_Pins/_delete_pin/should_perform_the_call_and_return_true.yml +109 -0
  102. data/spec/cassettes/Pinterest_Endpoints_Pins/_edit_pin/should_edit_the_pin_and_return_it_with_only_the_requested_fields.yml +56 -0
  103. data/spec/cassettes/Pinterest_Endpoints_Pins/_likes/should_only_get_requested_fields.yml +58 -0
  104. data/spec/cassettes/Pinterest_Endpoints_Pins/_likes/should_paginate_correctly.yml +87 -0
  105. data/spec/cassettes/Pinterest_Endpoints_Pins/_likes/should_return_the_list_of_liked_pins.yml +85 -0
  106. data/spec/cassettes/Pinterest_Endpoints_Pins/_pin/should_complain_for_non_existent_pins.yml +56 -0
  107. data/spec/cassettes/Pinterest_Endpoints_Pins/_pin/should_get_the_current_informations.yml +71 -0
  108. data/spec/cassettes/Pinterest_Endpoints_Pins/_pin/should_restrict_to_requested_fields.yml +56 -0
  109. data/spec/cassettes/Pinterest_Endpoints_Pins/_pins/should_only_get_requested_fields.yml +59 -0
  110. data/spec/cassettes/Pinterest_Endpoints_Pins/_pins/should_paginate_correctly.yml +808 -0
  111. data/spec/cassettes/Pinterest_Endpoints_Pins/_pins/should_return_my_pins.yml +88 -0
  112. data/spec/cassettes/Pinterest_Endpoints_Pins/_search_my_pins/should_only_get_requested_fields.yml +61 -0
  113. data/spec/cassettes/Pinterest_Endpoints_Pins/_search_my_pins/should_paginate_correctly.yml +89 -0
  114. data/spec/cassettes/Pinterest_Endpoints_Pins/_search_my_pins/should_search_my_pins.yml +89 -0
  115. data/spec/cassettes/Pinterest_Endpoints_Users/_follow_interest/should_perform_the_call_and_return_an_error.yml +48 -0
  116. data/spec/cassettes/Pinterest_Endpoints_Users/_follow_user/should_complain_for_invalid_users.yml +56 -0
  117. data/spec/cassettes/Pinterest_Endpoints_Users/_follow_user/should_perform_the_call_and_return_true.yml +109 -0
  118. data/spec/cassettes/Pinterest_Endpoints_Users/_followers/should_only_get_requested_fields.yml +62 -0
  119. data/spec/cassettes/Pinterest_Endpoints_Users/_followers/should_paginate_correctly.yml +62 -0
  120. data/spec/cassettes/Pinterest_Endpoints_Users/_followers/should_return_a_list_of_followers.yml +62 -0
  121. data/spec/cassettes/Pinterest_Endpoints_Users/_following_users/should_only_get_requested_fields.yml +62 -0
  122. data/spec/cassettes/Pinterest_Endpoints_Users/_following_users/should_paginate_correctly.yml +131 -0
  123. data/spec/cassettes/Pinterest_Endpoints_Users/_following_users/should_return_a_list_of_followed_users.yml +66 -0
  124. data/spec/cassettes/Pinterest_Endpoints_Users/_interests/should_paginate_correctly.yml +112 -0
  125. data/spec/cassettes/Pinterest_Endpoints_Users/_interests/should_return_a_list_of_followed_interest.yml +58 -0
  126. data/spec/cassettes/Pinterest_Endpoints_Users/_me/should_get_the_current_informations.yml +62 -0
  127. data/spec/cassettes/Pinterest_Endpoints_Users/_me/should_restrict_to_requested_fields.yml +56 -0
  128. data/spec/cassettes/Pinterest_Endpoints_Users/_unfollow_interest/should_perform_the_call_and_return_an_error.yml +48 -0
  129. data/spec/cassettes/Pinterest_Endpoints_Users/_unfollow_user/should_complain_for_invalid_users.yml +56 -0
  130. data/spec/cassettes/Pinterest_Endpoints_Users/_unfollow_user/should_perform_the_call_and_return_true.yml +109 -0
  131. data/spec/cassettes/Pinterest_Endpoints_Users/_user/should_complain_for_non_existent_users.yml +56 -0
  132. data/spec/cassettes/Pinterest_Endpoints_Users/_user/should_get_the_current_informations.yml +60 -0
  133. data/spec/cassettes/Pinterest_Endpoints_Users/_user/should_restrict_to_requested_fields.yml +56 -0
  134. data/spec/pinterest/client_spec.rb +70 -0
  135. data/spec/pinterest/collection_spec.rb +82 -0
  136. data/spec/pinterest/endpoints/authentication_spec.rb +81 -0
  137. data/spec/pinterest/endpoints/boards_spec.rb +209 -0
  138. data/spec/pinterest/endpoints/pins_spec.rb +239 -0
  139. data/spec/pinterest/endpoints/users_spec.rb +194 -0
  140. data/spec/pinterest/errors_spec.rb +59 -0
  141. data/spec/pinterest/fixtures/first.jpg +0 -0
  142. data/spec/pinterest/models/board_spec.rb +48 -0
  143. data/spec/pinterest/models/entity_spec.rb +35 -0
  144. data/spec/pinterest/models/image_spec.rb +50 -0
  145. data/spec/pinterest/models/interest_spec.rb +20 -0
  146. data/spec/pinterest/models/pin_spec.rb +55 -0
  147. data/spec/pinterest/models/user_spec.rb +45 -0
  148. data/spec/spec_helper.rb +49 -0
  149. data/tester.rb +19 -0
  150. metadata +341 -0
@@ -0,0 +1,110 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.7
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><h1>Top Level Namespace
63
+
64
+
65
+
66
+ </h1>
67
+ <div class="box_info">
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+ </div>
80
+
81
+ <h2>Defined Under Namespace</h2>
82
+ <p class="children">
83
+
84
+
85
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="FaradayMiddleware.html" title="FaradayMiddleware (module)">FaradayMiddleware</a></span>, <span class='object_link'><a href="Pinterest.html" title="Pinterest (module)">Pinterest</a></span>
86
+
87
+
88
+
89
+
90
+ </p>
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ </div>
101
+
102
+ <div id="footer">
103
+ Generated on Thu Jan 12 16:28:12 2017 by
104
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.7 (ruby-2.3.0).
106
+ </div>
107
+
108
+ </div>
109
+ </body>
110
+ </html>
@@ -0,0 +1,146 @@
1
+ #
2
+ # This file is part of the pinterest-ruby gem. Copyright (C) 2017 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ module Pinterest
7
+ # A Pinterest API client.
8
+ #
9
+ # @attribute access_token
10
+ # @return [String] The access token.
11
+ # @attribute client_id [String]
12
+ # @return The client id.
13
+ # @attribute client_secret [String]
14
+ # @return The client secret.
15
+ # @attribute verbose [Boolean]
16
+ # @return If log requests.
17
+ # @attribute connection_setup [Proc]
18
+ # @return Additional code to execute on the connection object.
19
+ class Client
20
+ # The Pinterest API Root URL.
21
+ API_URL = "https://api.pinterest.com".freeze
22
+
23
+ # The Pinterest API version.
24
+ API_VERSION = "v1".freeze
25
+
26
+ # The allowed authorization scopes.
27
+ SCOPES = ["read_public", "write_public", "read_relationships", "write_relationships"].freeze
28
+
29
+ # The maximum number of results to return by default.
30
+ DEFAULT_LIMIT = 50
31
+
32
+ attr_accessor :client_id, :client_secret, :access_token, :verbose, :connection
33
+
34
+ # Creates a new client.
35
+ #
36
+ # @param access_token [String] The access token.
37
+ # @param client_id [String] The client id.
38
+ # @param client_secret [String] The client secret.
39
+ # @param verbose [Boolean] If log requests.
40
+ # @param connection_setup [Proc] Additional code to execute on the connection object.
41
+ def initialize(access_token: nil, client_id: nil, client_secret: nil, verbose: false, &connection_setup)
42
+ @client_id = client_id
43
+ @client_secret = client_secret
44
+ @access_token = access_token
45
+ @verbose = verbose
46
+
47
+ ensure_connection(connection_setup)
48
+ end
49
+
50
+ include Pinterest::Endpoints::Authentication
51
+ include Pinterest::Endpoints::Users
52
+ include Pinterest::Endpoints::Pins
53
+ include Pinterest::Endpoints::Boards
54
+
55
+ private
56
+
57
+ # :nodoc:
58
+ def ensure_connection(setup = nil)
59
+ setup ||= ->(c) { default_connection_setup(c) }
60
+ @connection ||= Faraday.new(url: ::Pinterest::Client::API_URL, &setup)
61
+ end
62
+
63
+ # :nodoc:
64
+ def ensure_array(subject, default = [])
65
+ subject = (subject ? [subject] : [default]).flatten unless subject.is_a?(Array)
66
+ subject
67
+ end
68
+
69
+ # :nodoc:
70
+ def ensure_param(param, error = nil)
71
+ valid = param && !param.to_s.strip.empty?
72
+ raise(ArgumentError, error) if error && !valid
73
+ valid
74
+ end
75
+
76
+ # :nodoc:
77
+ def default_connection_setup(c)
78
+ c.request(:multipart)
79
+ c.request(:url_encoded)
80
+ c.response(:safe_oj)
81
+ c.response(:logger) if verbose
82
+
83
+ c.use(FaradayMiddleware::FollowRedirects)
84
+ c.adapter(Faraday.default_adapter)
85
+ end
86
+
87
+ # :nodoc:
88
+ def cleanup_params(params)
89
+ params.reject { |_, v| !ensure_param(v) }
90
+ end
91
+
92
+ # :nodoc:
93
+ # rubocop:disable Metrics/ParameterLists
94
+ def perform_network_request(method: "GET", url: "/", query: {}, body: {}, headers: {}, authenticated: true, pagination: false, **args, &additional)
95
+ response = connection.send(method.downcase) do |request|
96
+ # Setup URL and headers
97
+ setup_headers(request, url, headers, query, authenticated)
98
+
99
+ # Handle pagination
100
+ handle_pagination(request, args) if pagination
101
+
102
+ # Add the body
103
+ request.body = body
104
+
105
+ # Run user callback
106
+ yield(request) if additional
107
+ end
108
+
109
+ # Perform the call
110
+ raise(::Pinterest::Errors.create(response)) unless response.success?
111
+ response
112
+ rescue Faraday::ParsingError => e
113
+ handle_network_error(e)
114
+ end
115
+
116
+ # :nodoc:
117
+ def handle_network_error(e)
118
+ code = e.response.status
119
+ message = /<h1>(.+?)<\/h1>/mi.match(e.response.body)
120
+
121
+ raise(::Pinterest::Errors.class_for_code(code).new(code, message ? message[1] : "Invalid response from the server.", e.response))
122
+ end
123
+
124
+ # :nodoc:
125
+ def handle_pagination(request, args)
126
+ limit = args[:limit].to_i
127
+ limit = DEFAULT_LIMIT if limit < 1
128
+
129
+ request.params[:cursor] = args[:cursor] if args[:cursor]
130
+ request.params[:limit] = limit
131
+ end
132
+
133
+ # :nodoc:
134
+ def setup_headers(request, url, headers, query, authenticated)
135
+ request.url(url)
136
+ request.headers["Authorization"] = "Bearer #{access_token}" if authenticated
137
+ request.headers.merge!(headers)
138
+ request.params.merge!(query)
139
+ end
140
+
141
+ # :nodoc:
142
+ def versioned_url(url)
143
+ "/#{::Pinterest::Client::API_VERSION}/#{url.gsub(/^\//, "")}"
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,97 @@
1
+ #
2
+ # This file is part of the pinterest-ruby gem. Copyright (C) 2017 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ module Pinterest
7
+ # A collection of objects, including pagination data.
8
+ #
9
+ # @attribute records
10
+ # @return [Pinterest::Entity] A list of objects.
11
+ # @attribute limit
12
+ # @return [Fixnum] The maximum number of results to get from Pinterest API.
13
+ # @attribute current_cursor
14
+ # @return [String] The cursor to obtain the current page of results.
15
+ # @attribute next_cursor
16
+ # @return [String] The cursor to obtain the next page of results.
17
+ class Collection
18
+ attr_reader :records, :limit, :current_cursor, :next_cursor
19
+
20
+ # Creates a new collection. This class is for internal use.
21
+ #
22
+ # @param raw_data [Hash] A raw response obtained by Pinterest API.
23
+ # @param cursor [String] The current cursor.
24
+ # @param limit [Fixnum] The maximum number of records to obtain from Pinterest API.
25
+ # @param record_creator [Proc] The code to trasform each raw record in a object.
26
+ def initialize(raw_data, cursor, limit, &record_creator)
27
+ raise(ArgumentError, "raw_data must be an Hash.") unless raw_data.is_a?(Hash)
28
+ record_creator ||= ->(record) { record }
29
+
30
+ @limit = limit
31
+ @current_cursor = cursor
32
+ @next_cursor = raw_data["page"]["cursor"] if raw_data["page"] && raw_data["page"]["cursor"]
33
+ @records = raw_data.fetch("data", []).map(&record_creator)
34
+ end
35
+
36
+ # Returns a object from the collection.
37
+ #
38
+ # @param index [Fixnum] The index to get.
39
+ def [](index)
40
+ records[index]
41
+ end
42
+
43
+ # Returns the size of the collection.
44
+ #
45
+ # @return [Fixnum] The size of the collection.
46
+ def size
47
+ records.count
48
+ end
49
+
50
+ alias_method :count, :size
51
+ alias_method :length, :size
52
+
53
+ # Returns the current page cursor.
54
+ #
55
+ # @return [String] The current page cursor.
56
+ def current_page
57
+ current_cursor
58
+ end
59
+
60
+ # Returns the next page cursor.
61
+ #
62
+ # @return [String] The next page cursor.
63
+ def next_page
64
+ next_cursor
65
+ end
66
+
67
+ # Checks if the collection is empty.
68
+ #
69
+ # @return [Boolean] `true` if the collection is empty, `false` otherwise.
70
+ def empty?
71
+ records.empty?
72
+ end
73
+
74
+ # Checks if the collection has a next page.
75
+ #
76
+ # @return [Boolean] `true` if the collection has a next page, `false` otherwise.
77
+ def next?
78
+ !next_cursor.nil?
79
+ end
80
+
81
+ alias_method :next_page?, :next?
82
+ alias_method :eof?, :next?
83
+
84
+ # Serialize the collection as a Hash that can be serialized as JSON.
85
+ #
86
+ # @param options [Hash] The options to use to serialize.
87
+ # @return [Hash] The serialized collection.
88
+ def as_json(options = {})
89
+ {
90
+ records: records.as_json(options),
91
+ limit: limit,
92
+ current_cursor: current_cursor,
93
+ next_cursor: next_cursor
94
+ }
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,99 @@
1
+ #
2
+ # This file is part of the pinterest-ruby gem. Copyright (C) 2017 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ module Pinterest
7
+ # Pinterest API endpoints.
8
+ module Endpoints
9
+ # Authentication related endpoints.
10
+ module Authentication
11
+ # Returns a state string needed for authorization by the Pinterest API.
12
+ #
13
+ # @return [String] The state.
14
+ def authorization_state
15
+ @state ||= SecureRandom.hex
16
+ end
17
+
18
+ # Returns the URL to start the authentication flow.
19
+ #
20
+ # @param callback_url [String] The callback where to redirect the browser when done.
21
+ # @param scopes [Array] The list of scopes to ask for. For a list of valid fields, see `Pinterest::Client::SCOPES`.
22
+ # @return [String] The authorization URL.
23
+ def authorization_url(callback_url = nil, scopes = nil)
24
+ ensure_param(client_id, "You must specify the client_id.")
25
+ ensure_param(callback_url, "You must specify the callback_url.")
26
+ validate_callback_url(callback_url)
27
+
28
+ # Create the query
29
+ query = cleanup_params({
30
+ response_type: "code", client_id: client_id.to_s, authorization_state: authorization_state, redirect_uri: callback_url,
31
+ scope: (ensure_array(scopes, ::Pinterest::Client::SCOPES) & ::Pinterest::Client::SCOPES).join(",") # Restrict to only valid scopes
32
+ })
33
+
34
+ # Create the URL
35
+ url = Addressable::URI.parse(::Pinterest::Client::API_URL + "/oauth")
36
+ url.query_values = query
37
+ url.to_s
38
+ end
39
+
40
+ # Fetches the access token.
41
+ #
42
+ # @param [String] authorization_token The authorization token.
43
+ # @return [String] The authentication token.
44
+ def fetch_access_token(authorization_token)
45
+ ensure_param(client_id, "You must specify the client_id.")
46
+ ensure_param(client_secret, "You must specify the client_secret.")
47
+ ensure_param(authorization_token, "You must specify the authorization_token.")
48
+
49
+ # Create parameters
50
+ query = cleanup_params({
51
+ client_id: client_id, client_secret: client_secret,
52
+ grant_type: "authorization_code", code: authorization_token
53
+ })
54
+
55
+ # Perform the request and then get the token
56
+ response = perform_network_request(method: :post, url: versioned_url("/oauth/token"), query: query)
57
+ @access_token = response.body["access_token"]
58
+ end
59
+
60
+ # Verifies the access token.
61
+ #
62
+ # @return [Hash] The access token informations.
63
+ def verify_access_token
64
+ ensure_param(client_id, "You must specify the client_id.")
65
+ ensure_param(access_token, "You must set the access token first.")
66
+
67
+ # Get the data
68
+ data = perform_network_request(url: versioned_url("/oauth/inspect"), authenticated: true).body["data"]
69
+
70
+ # Prepare for output
71
+ create_authentication(data)
72
+ end
73
+
74
+ private
75
+
76
+ # :nodoc:
77
+ def validate_callback_url(url)
78
+ valid =
79
+ begin
80
+ Addressable::URI.parse(url).scheme == "https"
81
+ rescue
82
+ false
83
+ end
84
+
85
+ raise(ArgumentError, "callback_url must be a valid HTTPS URL.") unless valid
86
+ end
87
+
88
+ # :nodoc:
89
+ def create_authentication(data)
90
+ {
91
+ created_at: ::Pinterest::Entity.parse_timestamp(data["issued_at"]),
92
+ scopes: data["scopes"],
93
+ user_id: data["user_id"].to_s,
94
+ application_id: data["app"]["id"].to_s
95
+ }
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,193 @@
1
+ #
2
+ # This file is part of the pinterest-ruby gem. Copyright (C) 2017 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ module Pinterest
7
+ module Endpoints
8
+ # Boards related endpoints.
9
+ module Boards
10
+ # Returns information about a board.
11
+ #
12
+ # @param board [String] The board path (username/id) or user id.
13
+ # @param fields [Array] A list of fields to return.
14
+ # @return [Pinterest::Board] A board object.
15
+ def board(board, fields: nil)
16
+ # Validate the board id
17
+ board = validate_board(board)
18
+
19
+ # Ensure only valid fields are used
20
+ fields = ensure_board_fields(fields)
21
+
22
+ # Perform the request and create the board
23
+ data = perform_network_request(url: versioned_url("/boards/#{board}/"), query: cleanup_params({fields: fields.join(",")})).body["data"]
24
+ ::Pinterest::Board.create(data)
25
+ end
26
+
27
+ # Returns the list of the boards of the authenticated user. Pagination is not supported by Pinterest API.
28
+ #
29
+ # @param fields [Array] A list of fields to return.
30
+ # @return [Pinterest::Collection] An collection of board objects.
31
+ def boards(fields: nil)
32
+ get_boards_collection("/me/boards/", nil, fields)
33
+ end
34
+
35
+ # Creates a new board.
36
+ #
37
+ # @param name [String] The board name.
38
+ # @param description [String] The board description.
39
+ # @param fields [Array] A list of fields to return.
40
+ # @return [Pinterest::Board] The created board object.
41
+ def create_board(name, description = "", fields: nil)
42
+ # Validate name
43
+ ensure_param(name, "You have to specify the board name.")
44
+
45
+ # Ensure only valid fields are used
46
+ fields = ensure_board_fields(fields)
47
+
48
+ # Create the board
49
+ data = perform_network_request(
50
+ method: "POST", url: versioned_url("/boards/"),
51
+ query: cleanup_params({fields: fields.join(",")}),
52
+ body: cleanup_params({name: name, description: description})
53
+ )
54
+
55
+ # Wrap in a object
56
+ ::Pinterest::Board.create(data.body["data"])
57
+ end
58
+
59
+ # Edits a board.
60
+ #
61
+ # @param board [Fixnum] The board id.
62
+ # @param name [String] The new board name.
63
+ # @param description [String] The new board description.
64
+ # @param fields [Array] A list of fields to return.
65
+ # @return [Pinterest::Board] The updated board object.
66
+ def edit_board(board, name: nil, description: nil, fields: nil)
67
+ # Validate the board id
68
+ raise(ArgumentError, "You have to specify a board or its id.") unless board
69
+ board = board.id if board.is_a?(::Pinterest::Board)
70
+
71
+ # Ensure only valid fields are used
72
+ fields = ensure_board_fields(fields)
73
+
74
+ # Create the board
75
+ data = perform_network_request(
76
+ method: "PATCH", url: versioned_url("/boards/#{board}/"),
77
+ query: cleanup_params(fields: fields.join(",")),
78
+ body: cleanup_params({name: name, description: description})
79
+ )
80
+
81
+ # Wrap in a object
82
+ ::Pinterest::Board.create(data.body["data"])
83
+ end
84
+
85
+ # Deletes a board.
86
+ #
87
+ # @param board [Fixnum] The board id.
88
+ # @return [Boolean] `true` if operation succeeded, `false` otherwise.
89
+ def delete_board(board)
90
+ # Validate the board id
91
+ board = validate_board(board)
92
+
93
+ # Perform the request
94
+ perform_network_request(method: "DELETE", url: versioned_url("/boards/#{board}/"))
95
+ true
96
+ end
97
+
98
+ # Search between of boards of the authenticated user.
99
+ #
100
+ # @param query [String] The query to perform.
101
+ # @param fields [Array] A list of fields to return.
102
+ # @param cursor [String] A cursor to paginate results, obtained by a previous call.
103
+ # @param limit [Fixnum] The maximum number of objects to return.
104
+ # @return [Pinterest::Collection] An collection of board objects.
105
+ def search_my_boards(query, fields: nil, cursor: nil, limit: nil)
106
+ ensure_param(query, "You have to specify a query.")
107
+ get_boards_collection("/me/search/boards/", {query: query}, fields, cursor, limit)
108
+ end
109
+
110
+ # Returns the list of boards of suggested boards for the authenticated user.
111
+ #
112
+ # @param fields [Array] A list of fields to return.
113
+ # @param cursor [String] A cursor to paginate results, obtained by a previous call.
114
+ # @param limit [Fixnum] The maximum number of objects to return.
115
+ # @return [Pinterest::Collection] An collection of board objects.
116
+ def suggested_boards(fields: nil, cursor: nil, limit: nil)
117
+ get_boards_collection("/me/boards/suggested/", nil, fields, cursor, limit)
118
+ end
119
+
120
+ # Returns the list of boards followed by the authenticated user.
121
+ #
122
+ # @param fields [Array] A list of fields to return.
123
+ # @param cursor [String] A cursor to paginate results, obtained by a previous call.
124
+ # @param limit [Fixnum] The maximum number of objects to return.
125
+ # @return [Pinterest::Collection] An collection of board objects.
126
+ def following_boards(fields: nil, cursor: nil, limit: nil)
127
+ get_boards_collection("/me/following/boards/", nil, fields, cursor, limit)
128
+ end
129
+
130
+ # Follows a board.
131
+ #
132
+ # @param board [String] The board id.
133
+ # @return [Boolean] `true` if operation succeeded, `false` otherwise.
134
+ def follow_board(board)
135
+ # Validate the board id
136
+ board = validate_board(board)
137
+
138
+ # Perform the request
139
+ perform_network_request(method: "POST", query: {board: board}, url: versioned_url("/me/following/boards/"))
140
+ true
141
+ end
142
+
143
+ # Stop following a board.
144
+ #
145
+ # @param board [String] The board id.
146
+ # @return [Boolean] `true` if operation succeeded, `false` otherwise.
147
+ def unfollow_board(board)
148
+ # Validate the board id
149
+ board = validate_board(board)
150
+
151
+ # Perform the request
152
+ perform_network_request(method: "DELETE", url: versioned_url("/me/following/boards/#{board}/"))
153
+ true
154
+ end
155
+
156
+ private
157
+
158
+ # :nodoc:
159
+ def get_boards_collection(path, params, fields, cursor = nil, limit = nil)
160
+ # Ensure only valid fields are used and merge params
161
+ fields = ensure_board_fields(fields)
162
+ params ||= {}
163
+ params[:fields] = fields.join(",")
164
+
165
+ # Perform the request
166
+ data = perform_network_request(
167
+ url: versioned_url(path),
168
+ query: cleanup_params(params),
169
+ pagination: (cursor || limit), cursor: cursor, limit: limit
170
+ )
171
+
172
+ # Create the collection
173
+ ::Pinterest::Collection.new(data.body, cursor, limit) { |board| ::Pinterest::Board.create(board) }
174
+ end
175
+
176
+ # :nodoc:
177
+ def validate_board(board)
178
+ raise(ArgumentError, "You have to specify a board or its id.") unless board
179
+ board = board.id if board.is_a?(::Pinterest::Board)
180
+ board
181
+ end
182
+
183
+ # :nodoc:
184
+ def ensure_board_fields(fields = nil)
185
+ # Get fields and make sure only allowed fields are kept
186
+ fields = ensure_array(fields, ::Pinterest::Board::FIELDS).map(&:to_s) & ::Pinterest::Board::FIELDS
187
+
188
+ # Replace embedded fields
189
+ fields.map { |f| f == "creator" ? "creator(#{ensure_user_fields.join(",")})" : f }
190
+ end
191
+ end
192
+ end
193
+ end