flickr-objects 0.2.0 → 0.3.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 (92) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +49 -63
  3. data/lib/flickr/api/abstract/params_processor.rb +68 -0
  4. data/lib/flickr/api/abstract.rb +113 -0
  5. data/lib/flickr/api/general.rb +75 -0
  6. data/lib/flickr/api/person.rb +91 -39
  7. data/lib/flickr/api/photo.rb +213 -108
  8. data/lib/flickr/api/set.rb +114 -55
  9. data/lib/flickr/api/upload_ticket.rb +17 -6
  10. data/lib/flickr/api.rb +90 -35
  11. data/lib/flickr/attributes.rb +200 -0
  12. data/lib/flickr/base_converter.rb +29 -0
  13. data/lib/flickr/client/data.rb +47 -0
  14. data/lib/flickr/client/oauth.rb +44 -0
  15. data/lib/flickr/client/upload.rb +55 -0
  16. data/lib/flickr/client.rb +77 -33
  17. data/lib/flickr/configuration.rb +85 -14
  18. data/lib/flickr/error.rb +58 -0
  19. data/lib/flickr/middleware.rb +52 -28
  20. data/lib/flickr/oauth.rb +89 -74
  21. data/lib/flickr/object/attribute_locations/list.rb +25 -0
  22. data/lib/flickr/object/attribute_locations/location.rb +29 -0
  23. data/lib/flickr/object/attribute_locations/permissions.rb +31 -0
  24. data/lib/flickr/object/attribute_locations/person/upload_status.rb +32 -0
  25. data/lib/flickr/object/attribute_locations/person.rb +78 -0
  26. data/lib/flickr/object/attribute_locations/photo/exif.rb +29 -0
  27. data/lib/flickr/object/attribute_locations/photo/note.rb +36 -0
  28. data/lib/flickr/object/attribute_locations/photo/tag.rb +23 -0
  29. data/lib/flickr/object/attribute_locations/photo.rb +164 -0
  30. data/lib/flickr/object/attribute_locations/set.rb +53 -0
  31. data/lib/flickr/object/attribute_locations/upload_ticket.rb +30 -0
  32. data/lib/flickr/object/attribute_locations/visibility.rb +24 -0
  33. data/lib/flickr/object/list/kaminari.rb +30 -0
  34. data/lib/flickr/object/list/normal.rb +27 -0
  35. data/lib/flickr/object/list/will_paginate.rb +31 -0
  36. data/lib/flickr/object/list.rb +87 -0
  37. data/lib/flickr/object/location.rb +35 -0
  38. data/lib/flickr/object/permissions.rb +18 -0
  39. data/lib/flickr/object/person/upload_status.rb +22 -0
  40. data/lib/flickr/object/person.rb +93 -0
  41. data/lib/flickr/object/photo/exif.rb +35 -0
  42. data/lib/flickr/object/photo/note.rb +20 -0
  43. data/lib/flickr/object/photo/size.rb +67 -0
  44. data/lib/flickr/object/photo/tag.rb +23 -0
  45. data/lib/flickr/object/photo.rb +349 -0
  46. data/lib/flickr/object/set.rb +114 -0
  47. data/lib/flickr/object/upload_ticket.rb +31 -0
  48. data/lib/flickr/object/visibility.rb +16 -0
  49. data/lib/flickr/object.rb +118 -27
  50. data/lib/flickr/sanitized_file.rb +70 -0
  51. data/lib/flickr/version.rb +4 -2
  52. data/lib/flickr.rb +69 -15
  53. metadata +89 -103
  54. data/lib/flickr/api/api_methods/flickr.rb +0 -5
  55. data/lib/flickr/api/api_methods/person.rb +0 -14
  56. data/lib/flickr/api/api_methods/photo.rb +0 -26
  57. data/lib/flickr/api/api_methods/set.rb +0 -18
  58. data/lib/flickr/api/api_methods/upload_ticket.rb +0 -5
  59. data/lib/flickr/api/flickr.rb +0 -35
  60. data/lib/flickr/api_caller.rb +0 -98
  61. data/lib/flickr/client/methods_client.rb +0 -22
  62. data/lib/flickr/client/upload_client.rb +0 -62
  63. data/lib/flickr/errors.rb +0 -19
  64. data/lib/flickr/helpers/base_58.rb +0 -15
  65. data/lib/flickr/helpers/boolean.rb +0 -4
  66. data/lib/flickr/helpers/core_ext.rb +0 -5
  67. data/lib/flickr/object/attribute/converter.rb +0 -49
  68. data/lib/flickr/object/attribute/finder.rb +0 -32
  69. data/lib/flickr/object/attribute.rb +0 -45
  70. data/lib/flickr/objects/attribute_values/list.rb +0 -10
  71. data/lib/flickr/objects/attribute_values/location.rb +0 -14
  72. data/lib/flickr/objects/attribute_values/note.rb +0 -11
  73. data/lib/flickr/objects/attribute_values/permissions.rb +0 -12
  74. data/lib/flickr/objects/attribute_values/person/upload_status.rb +0 -16
  75. data/lib/flickr/objects/attribute_values/person.rb +0 -24
  76. data/lib/flickr/objects/attribute_values/photo.rb +0 -84
  77. data/lib/flickr/objects/attribute_values/set.rb +0 -17
  78. data/lib/flickr/objects/attribute_values/tag.rb +0 -9
  79. data/lib/flickr/objects/attribute_values/upload_ticket.rb +0 -9
  80. data/lib/flickr/objects/attribute_values/visibility.rb +0 -10
  81. data/lib/flickr/objects/list.rb +0 -86
  82. data/lib/flickr/objects/location.rb +0 -26
  83. data/lib/flickr/objects/note.rb +0 -14
  84. data/lib/flickr/objects/permissions.rb +0 -14
  85. data/lib/flickr/objects/person/upload_status.rb +0 -14
  86. data/lib/flickr/objects/person.rb +0 -43
  87. data/lib/flickr/objects/photo.rb +0 -113
  88. data/lib/flickr/objects/set.rb +0 -29
  89. data/lib/flickr/objects/tag.rb +0 -17
  90. data/lib/flickr/objects/upload_ticket.rb +0 -18
  91. data/lib/flickr/objects/visibility.rb +0 -12
  92. data/lib/flickr/objects.rb +0 -25
@@ -1,10 +1,46 @@
1
1
  require "cgi"
2
2
  require "faraday"
3
- require "flickr/errors"
4
3
  require "faraday_middleware/response_middleware"
4
+ require "flickr/error"
5
5
 
6
- class Flickr
6
+ module Flickr
7
+
8
+ ##
9
+ # A place for some custom middlewares for the API requests, mostly for translating
10
+ # Flickr errors into Ruby errors.
11
+ #
12
+ # @private
13
+ #
7
14
  module Middleware
15
+
16
+ ##
17
+ # Translates `Faraday::Error::TimeoutError` into `Flickr::TimeoutError`.
18
+ #
19
+ # @raise Flickr::TimeoutError
20
+ #
21
+ class CatchTimeout
22
+ def initialize(app)
23
+ @app = app
24
+ end
25
+
26
+ def call(env)
27
+ begin
28
+ @app.call(env)
29
+ rescue Faraday::Error::TimeoutError
30
+ raise Flickr::TimeoutError
31
+ end
32
+ end
33
+ end
34
+
35
+ ##
36
+ # Checks for errors in responses from Flickr, in which case it raises a
37
+ # `Flickr::ApiError` which contains the code and the message found in the response.
38
+ #
39
+ # It's a bit ugly because Flickr returns different error formats when uploading
40
+ # than when querying, so we need to take care of all cases.
41
+ #
42
+ # @raise Flickr::ApiError
43
+ #
8
44
  class CheckStatus < Faraday::Response::Middleware
9
45
  def on_complete(env)
10
46
  env[:body] = env[:body]["rsp"] || env[:body]
@@ -12,21 +48,32 @@ class Flickr
12
48
  if env[:body]["stat"] != "ok"
13
49
  message = env[:body]["message"] || env[:body]["err"]["msg"]
14
50
  code = env[:body]["code"] || env[:body]["err"]["code"]
15
- raise ApiError.new(message, code)
51
+
52
+ raise Flickr::ApiError.new(message, code)
16
53
  end
17
54
  end
18
55
  end
19
56
 
57
+ ##
58
+ # Checks for OAuth errors. They are in a different form than standard Flickr errors,
59
+ # so a special middleware is required.
60
+ #
61
+ # @raise Flickr::OAuthError
62
+ #
20
63
  class CheckOAuth < Faraday::Response::Middleware
21
64
  def on_complete(env)
22
65
  if env[:status] != 200
23
66
  message = CGI.parse(env[:body])["oauth_problem"].first
24
67
  pretty_message = message.gsub('_', ' ').capitalize
25
- raise OAuthError, pretty_message
68
+ raise Flickr::OAuthError, pretty_message
26
69
  end
27
70
  end
28
71
  end
29
72
 
73
+ ##
74
+ # Parses OAuth respones (which are in form of URL parameters). It subclasses
75
+ # FaradayMiddleware's internal `ResponseMiddleware` class for convenient parsing.
76
+ #
30
77
  class ParseOAuth < FaradayMiddleware::ResponseMiddleware
31
78
  define_parser do |body|
32
79
  CGI.parse(body).inject({}) do |hash, (key, value)|
@@ -35,29 +82,6 @@ class Flickr
35
82
  end
36
83
  end
37
84
 
38
- # A copy from Faraday (credits to @mislav)
39
- class Retry < Faraday::Middleware
40
- def initialize(app, options = {})
41
- super(app)
42
- @retries, options = options, {} if options.is_a? Integer
43
- @retries ||= options.fetch(:max, 2).to_i
44
- @sleep = options.fetch(:interval, 0).to_f
45
- @errmatch = options.fetch(:exceptions) { [Errno::ETIMEDOUT, 'Timeout::Error', Faraday::Error::TimeoutError] }
46
- end
47
-
48
- def call(env)
49
- retries = @retries
50
- begin
51
- @app.call(env)
52
- rescue *@errmatch => error
53
- if retries > 0
54
- retries -= 1
55
- sleep @sleep if @sleep > 0
56
- retry
57
- end
58
- raise Flickr::TimeoutError, error.message
59
- end
60
- end
61
- end
62
85
  end
86
+
63
87
  end
data/lib/flickr/oauth.rb CHANGED
@@ -1,109 +1,124 @@
1
- require "faraday"
2
- require "faraday_middleware"
3
- require "flickr/middleware"
4
-
5
- class Flickr
1
+ require "uri"
2
+
3
+ module Flickr
4
+
5
+ ##
6
+ # Interface for authenticating through OAuth.
7
+ #
8
+ # Example:
9
+ #
10
+ # request_token = Flickr::OAuth.get_request_token
11
+ # request_token.authorize_url
12
+ #
13
+ # # ... user visits the authorize URL, and gets the verifier ...
14
+ #
15
+ # access_token = request_token.get_access_token(verifier)
16
+ #
17
+ # access_token.key # "..."
18
+ # access_token.secret # "..."
19
+ # access_token.user_info # {username: "...", nsid: "...", ...}
20
+ #
6
21
  module OAuth
7
- URL = "http://www.flickr.com/services/oauth".freeze
8
- NO_CALLBACK = 'oob'.freeze
9
- DEFAULTS = Client::DEFAULTS
10
22
 
11
23
  extend self
12
24
 
13
- def get_request_token(options = {})
14
- response = connection.get "request_token" do |req|
15
- req.params[:oauth_callback] = options[:callback_url] || NO_CALLBACK
16
- end
17
-
18
- RequestToken.new(response.body)
25
+ ##
26
+ # @param params [Hash]
27
+ # @option params [String] :callback_url If the user is being authorized
28
+ # through another web application, this parameter can be used to redirect
29
+ # the user back to that application.
30
+ #
31
+ # @return [Flickr::OAuth::RequestToken]
32
+ #
33
+ def get_request_token(params = {})
34
+ params[:oauth_callback] = params.delete(:callback_url)
35
+ response = client.get_request_token(params)
36
+ RequestToken.new(response[:oauth_token], response[:oauth_token_secret])
19
37
  end
20
38
 
21
- def get_access_token(verifier, request_token)
22
- response = connection(request_token.to_a).get "access_token" do |req|
23
- req.params[:oauth_verifier] = verifier
24
- end
25
-
26
- AccessToken.new(response.body)
39
+ ##
40
+ # @param oauth_verifier [String] The code provided by Flickr after visiting
41
+ # the authorize URL.
42
+ # @param request_token [RequestToken, Array(String, String)]
43
+ #
44
+ # @return [Flickr::OAuth::AccessToken]
45
+ #
46
+ def get_access_token(oauth_verifier, request_token)
47
+ params = {oauth_verifier: oauth_verifier}
48
+ response = client(request_token.to_a).get_access_token(params)
49
+ AccessToken.new(response[:oauth_token], response[:oauth_token_secret],
50
+ response.reject { |key, value| [:oauth_token, :oauth_token_secret].include?(key) })
27
51
  end
28
52
 
29
53
  class Token
30
- attr_reader :token, :secret
31
-
32
- def initialize(*args)
33
- if args.first.is_a?(Hash)
34
- @token = args.first[:oauth_token]
35
- @secret = args.first[:oauth_token_secret]
36
- else
37
- @token = args.first
38
- @secret = args.last
39
- end
54
+ attr_reader :key, :secret
55
+ alias token key
56
+
57
+ ##
58
+ # @param key [String]
59
+ # @param secret [String]
60
+ #
61
+ def initialize(key, secret)
62
+ @key, @secret = key, secret
40
63
  end
41
64
 
42
65
  def to_a
43
- [token, secret]
66
+ [key, secret]
44
67
  end
45
68
  end
46
69
 
47
70
  class RequestToken < Token
71
+ ##
72
+ # @param params [Hash]
73
+ # @option params [String] :perms Optional. Can be `read`, `write`, or `delete`,
74
+ # depending on which permissions you want (for example, "flickr.photos.delete"
75
+ # requires `delete` permissions). If not specified, defaults to `write`.
76
+ #
48
77
  def authorize_url(params = {})
49
- require 'uri'
50
- url = URI.parse(URL)
51
- url.path += '/authorize'
78
+ url = URI.parse("http://www.flickr.com/services/oauth")
79
+ url.path += "/authorize"
52
80
  query_params = {oauth_token: token}.merge(params)
53
- url.query = query_params.map { |k,v| "#{k}=#{v}" }.join('&')
81
+ url.query = query_params.map { |k, v| "#{k}=#{v}" }.join("&")
54
82
  url.to_s
55
83
  end
56
84
 
57
- def get_access_token(verifier)
58
- OAuth.get_access_token(verifier, self)
85
+ ##
86
+ # @param oauth_verifier [String]
87
+ # @see Flickr::OAuth.get_access_token.
88
+ #
89
+ def get_access_token(oauth_verifier)
90
+ Flickr::OAuth.get_access_token(oauth_verifier, self)
59
91
  end
60
92
  end
61
93
 
62
94
  class AccessToken < Token
95
+ ##
96
+ # Holds user's information after authentication.
97
+ #
98
+ # @example
99
+ # {
100
+ # fullname: "Janko Marohnić",
101
+ # user_nsid: "78733179@N04",
102
+ # username: "@janko-m"
103
+ # }
104
+ #
63
105
  attr_reader :user_info
64
106
 
65
- def initialize(info)
66
- super
67
- @user_info = info.tap do |info|
68
- info.delete(:oauth_token)
69
- info.delete(:oauth_token_secret)
70
- end
107
+ ##
108
+ # @private
109
+ #
110
+ def initialize(key, secret, user_info)
111
+ super(key, secret)
112
+ @user_info = user_info
71
113
  end
72
114
  end
73
115
 
74
116
  private
75
117
 
76
- def connection(request_token = nil)
77
- api_key, shared_secret = Flickr.configuration.fetch(:api_key, :shared_secret)
78
-
79
- open_timeout = Flickr.configuration.open_timeout || DEFAULTS[:open_timeout]
80
- timeout = Flickr.configuration.timeout || DEFAULTS[:timeout]
81
-
82
- url = URL
83
- proxy = Flickr.configuration.proxy
84
-
85
- params = {
86
- url: url,
87
- request: {
88
- open_timeout: open_timeout,
89
- timeout: timeout
90
- },
91
- proxy: proxy
92
- }
93
-
94
- Faraday.new(params) do |builder|
95
- builder.use Middleware::Retry
96
- builder.use FaradayMiddleware::OAuth,
97
- consumer_key: api_key,
98
- consumer_secret: shared_secret,
99
- token: Array(request_token).first,
100
- token_secret: Array(request_token).last
101
-
102
- builder.use Middleware::ParseOAuth
103
- builder.use Middleware::CheckOAuth
104
-
105
- builder.adapter :net_http
106
- end
118
+ def client(request_token = nil)
119
+ Flickr::Client::OAuth.new(request_token)
107
120
  end
121
+
108
122
  end
123
+
109
124
  end
@@ -0,0 +1,25 @@
1
+ module Flickr
2
+ class Object
3
+
4
+ class List
5
+
6
+ attributes.add_locations(
7
+ current_page: [
8
+ -> { @attributes["page"] },
9
+ ],
10
+ per_page: [
11
+ -> { @attributes["per_page"] },
12
+ -> { @attributes["perpage"] },
13
+ ],
14
+ total_entries: [
15
+ -> { @attributes["total"] },
16
+ ],
17
+ total_pages: [
18
+ -> { @attributes["pages"] },
19
+ ],
20
+ )
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ module Flickr
2
+ class Object
3
+
4
+ class Location
5
+
6
+ Area.attributes.add_locations(
7
+ name: [
8
+ -> { @attributes["_content"] },
9
+ ],
10
+ woe_id: [
11
+ -> { @attributes["woeid"] },
12
+ ],
13
+ )
14
+
15
+ attributes.add_locations(
16
+ woe_id: [
17
+ -> { @attributes["woeid"] },
18
+ ],
19
+ indoors: [
20
+ -> { context == 1 },
21
+ ],
22
+ outdoors: [
23
+ -> { context == 2 },
24
+ ],
25
+ )
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ module Flickr
2
+ class Object
3
+
4
+ class Permissions
5
+
6
+ attributes.add_locations(
7
+ can_comment: [
8
+ -> { @attributes["cancomment"] },
9
+ -> { @attributes["can_comment"] }
10
+ ],
11
+ can_add_meta: [
12
+ -> { @attributes["canaddmeta"] },
13
+ ],
14
+ can_download: [
15
+ -> { @attributes["candownload"] },
16
+ ],
17
+ can_blog: [
18
+ -> { @attributes["canblog"] },
19
+ ],
20
+ can_print: [
21
+ -> { @attributes["canprint"] },
22
+ ],
23
+ can_share: [
24
+ -> { @attributes["canshare"] },
25
+ ],
26
+ )
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ module Flickr
2
+ class Object
3
+ class Person
4
+
5
+ class UploadStatus
6
+
7
+ Month.attributes.add_locations(
8
+ maximum: [
9
+ -> { @attributes["maxkb"] / 1024 },
10
+ ],
11
+ used: [
12
+ -> { @attributes["usedkb"] / 1024 },
13
+ ],
14
+ remaining: [
15
+ -> { @attributes["remainingkb"] / 1024 },
16
+ ],
17
+ )
18
+
19
+ attributes.add_locations(
20
+ current_month: [
21
+ -> { @attributes["bandwidth"] },
22
+ ],
23
+ maximum_photo_size: [
24
+ -> { @attributes["filesize"]["maxmb"] },
25
+ ],
26
+ )
27
+
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,78 @@
1
+ module Flickr
2
+ class Object
3
+
4
+ class Person
5
+
6
+ attributes.add_locations(
7
+ id: [
8
+ -> { @attributes["nsid"] },
9
+ ],
10
+ nsid: [
11
+ -> { id },
12
+ ],
13
+ username: [
14
+ -> { @attributes["username"]["_content"] },
15
+ ],
16
+ real_name: [
17
+ -> { @attributes["realname"].fetch("_content") },
18
+ -> { @attributes["realname"] },
19
+ ],
20
+ icon_server: [
21
+ -> { @attributes["iconserver"] },
22
+ ],
23
+ icon_farm: [
24
+ -> { @attributes["iconfarm"] },
25
+ ],
26
+ buddy_icon_url: [
27
+ -> {
28
+ if icon_farm && icon_server && id
29
+ if icon_server > 0
30
+ "http://farm#{icon_farm}.staticflickr.com/#{icon_server}/buddyicons/#{id}.jpg"
31
+ else
32
+ "http://www.flickr.com/images/buddyicon.jpg"
33
+ end
34
+ end
35
+ },
36
+ ],
37
+ has_pro_account: [
38
+ -> { @attributes["ispro"] },
39
+ ],
40
+ location: [
41
+ -> { @attributes["location"]["_content"] },
42
+ ],
43
+ time_zone: [
44
+ -> { @attributes["timezone"] },
45
+ ],
46
+ description: [
47
+ -> { @attributes["description"]["_content"] },
48
+ ],
49
+ photos_url: [
50
+ -> { @attributes["photosurl"]["_content"] },
51
+ ],
52
+ profile_url: [
53
+ -> { @attributes["profileurl"]["_content"] },
54
+ ],
55
+ mobile_url: [
56
+ -> { @attributes["mobileurl"]["_content"] },
57
+ ],
58
+ first_photo_taken: [
59
+ -> { @attributes["photos"]["firstdatetaken"]["_content"] },
60
+ ],
61
+ first_photo_uploaded: [
62
+ -> { @attributes["photos"]["firstdate"]["_content"] },
63
+ ],
64
+ favorited_at: [
65
+ -> { @attributes["favedate"] },
66
+ ],
67
+ photos_count: [
68
+ -> { @attributes["photos"]["count"]["_content"] },
69
+ ],
70
+ photo_views_count: [
71
+ -> { @attributes["photos"]["views"]["_content"] },
72
+ ],
73
+ )
74
+
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,29 @@
1
+ module Flickr
2
+ class Object
3
+ class Photo
4
+
5
+ class Exif
6
+
7
+ attributes.add_locations(
8
+ items: [
9
+ -> { @attributes },
10
+ ],
11
+ )
12
+
13
+ Item.attributes.add_locations(
14
+ tagspace_id: [
15
+ -> { @attributes["tagspaceid"] },
16
+ ],
17
+ raw: [
18
+ -> { @attributes["raw"]["_content"] },
19
+ ],
20
+ clean: [
21
+ -> { @attributes["clean"]["_content"] },
22
+ ],
23
+ )
24
+
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,36 @@
1
+ module Flickr
2
+ class Object
3
+ class Photo
4
+
5
+ class Note
6
+
7
+ attributes.add_locations(
8
+ author: [
9
+ -> {
10
+ if @attributes["author"]
11
+ {
12
+ "id" => @attributes["author"],
13
+ "username" => @attributes["authorname"],
14
+ }
15
+ end
16
+ },
17
+ ],
18
+ coordinates: [
19
+ -> { [@attributes["x"], @attributes["y"]] if @attributes["x"] },
20
+ ],
21
+ width: [
22
+ -> { @attributes["w"] },
23
+ ],
24
+ height: [
25
+ -> { @attributes["h"] },
26
+ ],
27
+ content: [
28
+ -> { @attributes["_content"] },
29
+ ],
30
+ )
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ module Flickr
2
+ class Object
3
+ class Photo
4
+
5
+ class Tag
6
+
7
+ attributes.add_locations(
8
+ author: [
9
+ -> { {"id" => @attributes.fetch("author")} },
10
+ ],
11
+ content: [
12
+ -> { @attributes["_content"] },
13
+ ],
14
+ machine_tag: [
15
+ -> { @attributes["machine_tag"] },
16
+ ],
17
+ )
18
+
19
+ end
20
+
21
+ end
22
+ end
23
+ end