unsplash_mango 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.
@@ -0,0 +1,29 @@
1
+ module Unsplash # :nodoc:
2
+ class Configuration # :nodoc:
3
+ attr_accessor :application_access_key
4
+ attr_accessor :application_secret
5
+ attr_accessor :application_redirect_uri
6
+ attr_accessor :logger
7
+ attr_accessor :utm_source
8
+ attr_writer :test
9
+
10
+ def initialize
11
+ @test = true
12
+ @logger = Logger.new(STDOUT)
13
+ end
14
+
15
+ def test?
16
+ !!@test
17
+ end
18
+
19
+ def application_id=(key)
20
+ logger.warn "Configuring application_id is deprecated. Use application_access_key."
21
+ self.application_access_key = key
22
+ end
23
+
24
+ def application_id
25
+ application_access_key
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,157 @@
1
+ module Unsplash #:nodoc:
2
+
3
+ # HTTP connection to and communication with the Unsplash API.
4
+ class Connection
5
+ include HTTParty
6
+
7
+ # The version of the API being used if unspecified.
8
+ DEFAULT_VERSION = "v1"
9
+
10
+ # Base URI for the Unsplash API..
11
+ DEFAULT_API_BASE_URI = "https://api.unsplash.com"
12
+
13
+ # Base URI for Unsplash OAuth.
14
+ DEFAULT_OAUTH_BASE_URI = "https://unsplash.com"
15
+
16
+ # Create a Connection object.
17
+ # @param version [String] The Unsplash API version to use.
18
+ # @param api_base_uri [String] Base URI at which to make API calls.
19
+ # @param oauth_base_uri [String] Base URI for OAuth requests.
20
+ def initialize(version: DEFAULT_VERSION, api_base_uri: DEFAULT_API_BASE_URI, oauth_base_uri: DEFAULT_OAUTH_BASE_URI)
21
+ @application_access_key = Unsplash.configuration.application_access_key
22
+ @application_secret = Unsplash.configuration.application_secret
23
+ @api_version = version
24
+ @api_base_uri = api_base_uri
25
+
26
+ oauth_base_uri = oauth_base_uri
27
+ @oauth = ::OAuth2::Client.new(@application_access_key, @application_secret, site: oauth_base_uri) do |http|
28
+ http.request :multipart
29
+ http.request :url_encoded
30
+ http.adapter :net_http
31
+ end
32
+
33
+ Unsplash::Connection.base_uri @api_base_uri
34
+ end
35
+
36
+ # Get OAuth URL for user authentication and authorization.
37
+ # @param requested_scopes [Array] An array of permission scopes being requested.
38
+ # @return [String] The authorization URL.
39
+ def authorization_url(requested_scopes = ["public"])
40
+ @oauth.auth_code.authorize_url(redirect_uri: Unsplash.configuration.application_redirect_uri,
41
+ scope: requested_scopes.join(" "))
42
+ end
43
+
44
+ # Generate an access token given an auth code received from Unsplash.
45
+ # This is used internally to authenticate and authorize future user actions.
46
+ # @param auth_code [String] The OAuth authentication code from Unsplash.
47
+ def authorize!(auth_code)
48
+ @oauth_token = @oauth.auth_code.get_token(auth_code, redirect_uri: Unsplash.configuration.application_redirect_uri)
49
+ # TODO check if it succeeded
50
+ end
51
+
52
+ # Extract hash with OAuth token attributes. Extracted token attributes can
53
+ # be used with create_and_assign_token to prevent the need for
54
+ # reauthorization.
55
+ # @return [Hash, nil] @oauth_token converted to a hash.
56
+ def extract_token
57
+ @oauth_token.to_hash if @oauth_token
58
+ end
59
+
60
+ # Create and assign new access token from extracted token. To be used with
61
+ # extract_token to reauthorize app without api call.
62
+ # @param token_extract [Hash] OAuth token hash from #extract_token.
63
+ # @return [OAuth2::AccessToken, nil] New access token object.
64
+ def create_and_assign_token(token_extract)
65
+ unless token_extract.nil?
66
+ @oauth_token = OAuth2::AccessToken.from_hash(@oauth, token_extract)
67
+ end
68
+ end
69
+
70
+ # Perform a GET request.
71
+ # @param path [String] The path at which to make ther request.
72
+ # @param params [Hash] A hash of request parameters.
73
+ def get(path, params = {})
74
+ request :get, path, params
75
+ end
76
+
77
+ # Perform a PUT request.
78
+ # @param path [String] The path at which to make ther request.
79
+ # @param params [Hash] A hash of request parameters.
80
+ def put(path, params = {})
81
+ request :put, path, params
82
+ end
83
+
84
+ # Perform a POST request.
85
+ # @param path [String] The path at which to make ther request.
86
+ # @param params [Hash] A hash of request parameters.
87
+ def post(path, params = {})
88
+ request :post, path, params
89
+ end
90
+
91
+ # Perform a DELETE request.
92
+ # @param path [String] The path at which to make ther request.
93
+ # @param params [Hash] A hash of request parameters.
94
+ def delete(path, params = {})
95
+ request :delete, path, params
96
+ end
97
+
98
+ private
99
+
100
+ def request(verb, path, params = {})
101
+ raise ArgumentError.new "Invalid http verb #{verb}" if ![:get, :post, :put, :delete].include?(verb)
102
+
103
+ params.merge!(utm_params)
104
+
105
+ if !Unsplash.configuration.utm_source
106
+ url = "https://community.unsplash.com/developersblog/unsplash-api-guidelines"
107
+ Unsplash.configuration.logger.warn "utm_source is required as part of API Terms: #{url}"
108
+ end
109
+
110
+ headers = {
111
+ "Accept-Version" => @api_version
112
+ # Anything else? User agent?
113
+ }
114
+
115
+ response = if @oauth_token
116
+ refresh_token!
117
+
118
+ param_key = verb == :post ? :body : :params
119
+ @oauth_token.public_send(verb, @api_base_uri + path, param_key => params, headers: headers)
120
+ else
121
+ self.class.public_send verb, path, query: params, headers: public_auth_header
122
+ end
123
+
124
+ if response.headers["Warning"]
125
+ Unsplash.configuration.logger.warn response.headers["Warning"]
126
+ end
127
+
128
+ status_code = response.respond_to?(:status) ? response.status : response.code
129
+
130
+ if !(200..299).include?(status_code)
131
+ body = JSON.parse(response.body)
132
+ msg = body["error"] || body["errors"].join(" ")
133
+ raise Unsplash::Error.new msg
134
+ end
135
+
136
+ response
137
+ end
138
+
139
+ def public_auth_header
140
+ { "Authorization" => "Client-ID #{@application_access_key}" }
141
+ end
142
+
143
+ def utm_params
144
+ {
145
+ utm_source: Unsplash.configuration.utm_source || "api_app",
146
+ utm_medium: "referral",
147
+ utm_campaign: "api-credit"
148
+ }
149
+ end
150
+
151
+ def refresh_token!
152
+ return if !@oauth_token.expired?
153
+
154
+ @oauth_token = @oauth_token.refresh_token
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,43 @@
1
+ module Unsplash # :nodoc:
2
+
3
+ # Unsplash Curated Batch operations.
4
+ class CuratedBatch < Client
5
+
6
+ class << self
7
+
8
+ # Get a specific curated batch.
9
+ # @param id [Integer] The ID of the batch.
10
+ # @return [Unsplash::CuratedBatch] The requested batch.
11
+ def find(id)
12
+ batch = Unsplash::CuratedBatch.new JSON.parse(connection.get("/curated_batches/#{id}").body)
13
+ batch.curator = Unsplash::User.new batch.curator
14
+ batch
15
+ end
16
+
17
+ # Get a list of all curated batches.
18
+ # @param page [Integer] Which page of search results to return.
19
+ # @param per_page [Integer] The number of search results per page.
20
+ # @return [Array] A single page of the +Unsplash::CuratedBatch+ list.
21
+ def all(page = 1, per_page = 10)
22
+ params = {
23
+ page: page,
24
+ per_page: per_page
25
+ }
26
+ list = JSON.parse(connection.get("/curated_batches/", params).body)
27
+ list.map do |cb|
28
+ batch = Unsplash::CuratedBatch.new cb
29
+ batch.curator = Unsplash::User.new batch.curator
30
+ batch
31
+ end
32
+ end
33
+ end
34
+
35
+ # Get a list of the photos contained in this batch.
36
+ # @return [Array] The list of +Unsplash::Photo+s in the batch.
37
+ def photos
38
+ list = JSON.parse(connection.get("/curated_batches/#{id}/photos").body)
39
+ list.map { |photo| Unsplash::Photo.new photo }
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,6 @@
1
+ module Unsplash # :nodoc:
2
+ # Raised when there is an error communicating with Unsplash.
3
+ class Error < StandardError; end
4
+ # Raise for deprecation errors
5
+ class DeprecationError < Error; end
6
+ end
@@ -0,0 +1,142 @@
1
+ module Unsplash # :nodoc:
2
+
3
+ # Unsplash Photo operations.
4
+ class Photo < Client
5
+
6
+ # Like a photo for the current user.
7
+ # @return [Boolean] True if successful. Will raise on error.
8
+ def like!
9
+ connection.post("/photos/#{id}/like")
10
+ true
11
+ end
12
+
13
+ # Unlike a photo for the current user.
14
+ # @return [Boolean] True if successful. Will raise on error.
15
+ def unlike!
16
+ connection.delete("/photos/#{id}/like")
17
+ true
18
+ end
19
+
20
+ # Download a photo.
21
+ # @return [String] URL of image file for download.
22
+ def download!
23
+ connection.get(links.download_location)["url"]
24
+ end
25
+
26
+ class << self
27
+
28
+ # Get a photo. Can be cropped or resized using the optional parameters.
29
+ # @param id [String] The ID of the photo to retrieve.
30
+ # @param width [Integer] Width of customized version of the photo.
31
+ # @param height [Integer] Height of the customized version of the photo.
32
+ # @param crop_rect [String] A comma-separated list (x,y,width,height) of the rectangle to crop from the photo.
33
+ # @return [Unsplash::Photo] The Unsplash Photo.
34
+ def find(id, width: nil, height: nil, crop_rect: nil)
35
+ custom = {
36
+ w: width,
37
+ h: height,
38
+ rect: crop_rect
39
+ }.select { |k,v| v }
40
+ photo = Unsplash::Photo.new JSON.parse(connection.get("/photos/#{id}", custom).body)
41
+ photo.user = Unsplash::User.new photo.user
42
+ photo
43
+ end
44
+
45
+ # Get a random photo or set of photos. The photo selection pool can be narrowed using
46
+ # a combination of optional parameters. Can also optionally specify a custom image size.
47
+ # @param count [Integer] Number of photos required. Default=1, Max=30
48
+ # @param categories [Array] Limit selection to given category ID's.
49
+ # @param featured [Boolean] Limit selection to featured photos.
50
+ # @param user [String] Limit selection to given User's ID.
51
+ # @param query [String] Limit selection to given search query.
52
+ # @param width [Integer] Width of customized version of the photo.
53
+ # @param height [Integer] Height of the customized version of the photo.
54
+ # @param orientation [String] Filter by orientation of the photo. Valid values are landscape, portrait, and squarish.
55
+ # @return [Unsplash::Photo] An Unsplash Photo if count parameter is omitted
56
+ # @return [Array] An array of Unsplash Photos if the count parameter is specified. An array is returned even if count is 1
57
+ def random(count: nil, categories: nil, collections: nil, featured: nil, user: nil, query: nil, width: nil, height: nil, orientation: nil)
58
+ params = {
59
+ category: (categories && categories.join(",")),
60
+ collections: (collections && collections.join(",")),
61
+ featured: featured,
62
+ username: user,
63
+ query: query,
64
+ w: width,
65
+ h: height,
66
+ orientation: orientation
67
+ }.select { |k,v| v }
68
+ if count
69
+ params[:count] = count
70
+ photos = parse_list connection.get("/photos/random/", params).body
71
+ photos.map { |photo|
72
+ photo.user = Unsplash::User.new photo[:user]
73
+ photo
74
+ }
75
+ else
76
+ photo = Unsplash::Photo.new JSON.parse(connection.get("/photos/random", params).body)
77
+ photo.user = Unsplash::User.new photo.user
78
+ photo
79
+ end
80
+ end
81
+
82
+ # Search for photos by keyword.
83
+ # @param query [String] Keywords to search for.
84
+ # @param page [Integer] Which page of search results to return.
85
+ # @param per_page [Integer] The number of users search result per page. (default: 10, maximum: 30)
86
+ # @param orientation [String] Filter by orientation of the photo. Valid values are landscape, portrait, and squarish.
87
+ # @return [SearchResult] a list of +Unsplash::Photo+ objects.
88
+ def search(query, page = 1, per_page = 10, orientation = nil)
89
+ params = {
90
+ query: query,
91
+ page: page,
92
+ per_page: per_page,
93
+ orientation: orientation
94
+ }.select { |_k, v| v }
95
+ Unsplash::Search.search("/search/photos", self, params)
96
+ end
97
+
98
+ # Get a list of all photos.
99
+ # @param page [Integer] Which page of search results to return.
100
+ # @param per_page [Integer] The number of search results per page. (default: 10, maximum: 30)
101
+ # @param order_by [String] How to sort the photos. (Valid values: latest, oldest, popular; default: latest)
102
+ # @return [Array] A single page of +Unsplash::Photo+ search results.
103
+ def all(page = 1, per_page = 10, order_by = "latest")
104
+ params = {
105
+ page: page,
106
+ per_page: per_page,
107
+ order_by: order_by
108
+ }
109
+ parse_list connection.get("/photos/", params).body
110
+ end
111
+
112
+ # Get a single page from the list of the curated photos (front-page’s photos).
113
+ # @param page [Integer] Which page of search results to return.
114
+ # @param per_page [Integer] The number of search results per page. (default: 10, maximum: 30)
115
+ # @param order_by [String] How to sort the photos. (Valid values: latest, oldest, popular; default: latest)
116
+ # @return [Array] A single page of +Unsplash::Photo+ search results.
117
+ def curated(page = 1, per_page = 10, order_by = "latest")
118
+ params = {
119
+ page: page,
120
+ per_page: per_page,
121
+ order_by: order_by
122
+ }
123
+ parse_list connection.get("/photos/curated", params).body
124
+ end
125
+
126
+ # Upload a photo on behalf of the current user.
127
+ # @param filepath [String] The local path of the image file to upload.
128
+ # @return [Unsplash::Photo] The uploaded photo.
129
+ # <b>DEPRECATED</b>
130
+ def create(filepath)
131
+ raise Unsplash::DeprecationError.new "API photo-upload endpoint has been deprecated and removed."
132
+ end
133
+
134
+ private
135
+
136
+ def parse_list(json)
137
+ JSON.parse(json).map { |photo| new photo }
138
+ end
139
+
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,34 @@
1
+ module Unsplash # :nodoc:
2
+
3
+ # Decorates Array of klass-type objects with total and total_pages attributes
4
+ class SearchResult < SimpleDelegator
5
+ attr_reader :total, :total_pages
6
+
7
+ def initialize(decorated, klass)
8
+ @total = decorated["total"]
9
+ @total_pages = decorated["total_pages"]
10
+
11
+ list = decorated["results"].map do |content|
12
+ klass.new content.to_hash
13
+ end
14
+
15
+ super(list)
16
+ end
17
+ end
18
+
19
+ # Unsplash Search operations
20
+ class Search < Client
21
+
22
+ class << self
23
+ # Helper class to facilitate search on multiple classes
24
+ # @param url [String] Url to be searched into
25
+ # @param klass [Class] Class to instantiate the contents with
26
+ # @param params [Hash] Params for the search
27
+ # @return [SearchResult] Decorated Array of klass-type objects
28
+ def search(url, klass, params)
29
+ list = JSON.parse(connection.get(url, params).body)
30
+ SearchResult.new(list, klass)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ module Unsplash # :nodoc:
2
+
3
+ # Retrieve Unsplash stats
4
+ class Stats < Client
5
+
6
+ class << self
7
+ # Get a list of statistics regardling Unsplash as a whole.
8
+ # @return [Hash] The numbers.
9
+ def total
10
+ JSON.parse(connection.get("/stats/total").body)
11
+ end
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,93 @@
1
+ module Unsplash # :nodoc:
2
+
3
+ # Unsplash User operations.
4
+ class User < Client
5
+
6
+ class << self
7
+
8
+ # Get a user.
9
+ # @param username [String] the username of the user to retrieve.
10
+ # @return [Unsplash::User] the Unsplash User.
11
+ def find(username)
12
+ new JSON.parse(connection.get("/users/#{username}").body)
13
+ end
14
+
15
+ # Get the currently-logged in user.
16
+ # @return [Unsplash::User] the current user.
17
+ def current
18
+ new JSON.parse(connection.get("/me").body)
19
+ end
20
+
21
+ # Update the current user.
22
+ # @param params [Hash] the hash of attributes to update.
23
+ # @return [Unsplash::User] the updated user.
24
+ def update_current(params)
25
+ Unsplash::User.new JSON.parse(connection.put("/me", params).body)
26
+ end
27
+
28
+ # Get a single page of user results for a query.
29
+ # @param query [String] Keywords to search for.
30
+ # @param page [Integer] Which page of search results to return.
31
+ # @param per_page [Integer] The number of users search result per page. (default: 10, maximum: 30)
32
+ # @return [Array] a list of +Unsplash::User+ objects.
33
+ def search(query, page = 1, per_page = 10)
34
+ params = {
35
+ query: query,
36
+ page: page,
37
+ per_page: per_page
38
+ }
39
+ Unsplash::Search.search("/search/users", self, params)
40
+ end
41
+
42
+ end
43
+
44
+ # Get a list of photos uploaded by the user.
45
+ # @param page [Integer] Which page of results to return.
46
+ # @param per_page [Integer] The number of results per page.
47
+ # @return [Array] a list of +Unsplash::Photo+ objects.
48
+ def photos(page = 1, per_page = 10)
49
+ params = {
50
+ page: page,
51
+ per_page: per_page
52
+ }
53
+
54
+ list = JSON.parse(connection.get("/users/#{username}/photos", params).body)
55
+ list.map do |photo|
56
+ Unsplash::Photo.new photo.to_hash
57
+ end
58
+ end
59
+
60
+ # Get a list of photos liked by the user.
61
+ # @param page [Integer] Which page of results to return.
62
+ # @param per_page [Integer] The number of results per page. (default: 10, maximum: 30)
63
+ # @return [Array] a list of +Unsplash::Photo+ objects.
64
+ def likes(page = 1, per_page = 10)
65
+ params = {
66
+ page: page,
67
+ per_page: per_page
68
+ }
69
+
70
+ list = JSON.parse(connection.get("/users/#{username}/likes", params).body)
71
+ list.map do |photo|
72
+ Unsplash::Photo.new photo.to_hash
73
+ end
74
+ end
75
+
76
+ # Get a list of collections created by the user.
77
+ # @param page [Integer] Which page of results to return.
78
+ # @param per_page [Integer] The number of results per page. (default: 10, maximum: 30)
79
+ # @return [Array] a list of +Unsplash::Collection+ objects.
80
+ def collections(page = 1, per_page = 10)
81
+ params = {
82
+ page: page,
83
+ per_page: per_page
84
+ }
85
+
86
+ list = JSON.parse(connection.get("/users/#{username}/collections", params).body)
87
+ list.map do |collection|
88
+ Unsplash::Collection.new collection.to_hash
89
+ end
90
+ end
91
+
92
+ end
93
+ end