flickr-objects 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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