theoooo-fleakr 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +350 -0
- data/Rakefile +41 -0
- data/lib/fleakr.rb +163 -0
- data/lib/fleakr/api.rb +8 -0
- data/lib/fleakr/api/file_parameter.rb +47 -0
- data/lib/fleakr/api/method_request.rb +66 -0
- data/lib/fleakr/api/option.rb +175 -0
- data/lib/fleakr/api/parameter.rb +35 -0
- data/lib/fleakr/api/parameter_list.rb +97 -0
- data/lib/fleakr/api/response.rb +35 -0
- data/lib/fleakr/api/upload_request.rb +75 -0
- data/lib/fleakr/api/value_parameter.rb +36 -0
- data/lib/fleakr/core_ext.rb +3 -0
- data/lib/fleakr/core_ext/false_class.rb +7 -0
- data/lib/fleakr/core_ext/hash.rb +22 -0
- data/lib/fleakr/core_ext/true_class.rb +7 -0
- data/lib/fleakr/objects.rb +12 -0
- data/lib/fleakr/objects/authentication_token.rb +60 -0
- data/lib/fleakr/objects/comment.rb +49 -0
- data/lib/fleakr/objects/contact.rb +31 -0
- data/lib/fleakr/objects/error.rb +22 -0
- data/lib/fleakr/objects/group.rb +36 -0
- data/lib/fleakr/objects/image.rb +50 -0
- data/lib/fleakr/objects/photo.rb +147 -0
- data/lib/fleakr/objects/photo_context.rb +49 -0
- data/lib/fleakr/objects/search.rb +30 -0
- data/lib/fleakr/objects/set.rb +50 -0
- data/lib/fleakr/objects/tag.rb +56 -0
- data/lib/fleakr/objects/user.rb +95 -0
- data/lib/fleakr/support.rb +2 -0
- data/lib/fleakr/support/attribute.rb +46 -0
- data/lib/fleakr/support/object.rb +110 -0
- data/lib/fleakr/version.rb +13 -0
- data/test/fixtures/auth.checkToken.xml +8 -0
- data/test/fixtures/auth.getFullToken.xml +8 -0
- data/test/fixtures/auth.getToken.xml +8 -0
- data/test/fixtures/contacts.getPublicList.xml +7 -0
- data/test/fixtures/groups.pools.getPhotos.xml +7 -0
- data/test/fixtures/people.findByEmail.xml +6 -0
- data/test/fixtures/people.findByUsername.xml +6 -0
- data/test/fixtures/people.getInfo.xml +18 -0
- data/test/fixtures/people.getPublicGroups.xml +7 -0
- data/test/fixtures/people.getPublicPhotos.xml +7 -0
- data/test/fixtures/photos.comments.getList.xml +7 -0
- data/test/fixtures/photos.getContext.xml +6 -0
- data/test/fixtures/photos.getInfo.xml +20 -0
- data/test/fixtures/photos.getSizes.xml +10 -0
- data/test/fixtures/photos.search.xml +7 -0
- data/test/fixtures/photosets.comments.getList.xml +7 -0
- data/test/fixtures/photosets.getList.xml +13 -0
- data/test/fixtures/photosets.getPhotos.xml +7 -0
- data/test/fixtures/tags.getListPhoto.xml +9 -0
- data/test/fixtures/tags.getListUser.xml +10 -0
- data/test/fixtures/tags.getRelated.xml +9 -0
- data/test/test_helper.rb +140 -0
- data/test/unit/fleakr/api/file_parameter_test.rb +63 -0
- data/test/unit/fleakr/api/method_request_test.rb +93 -0
- data/test/unit/fleakr/api/option_test.rb +179 -0
- data/test/unit/fleakr/api/parameter_list_test.rb +176 -0
- data/test/unit/fleakr/api/parameter_test.rb +34 -0
- data/test/unit/fleakr/api/response_test.rb +49 -0
- data/test/unit/fleakr/api/upload_request_test.rb +145 -0
- data/test/unit/fleakr/api/value_parameter_test.rb +41 -0
- data/test/unit/fleakr/core_ext/false_class_test.rb +13 -0
- data/test/unit/fleakr/core_ext/hash_test.rb +32 -0
- data/test/unit/fleakr/core_ext/true_class_test.rb +13 -0
- data/test/unit/fleakr/objects/authentication_token_test.rb +61 -0
- data/test/unit/fleakr/objects/comment_test.rb +66 -0
- data/test/unit/fleakr/objects/contact_test.rb +58 -0
- data/test/unit/fleakr/objects/error_test.rb +21 -0
- data/test/unit/fleakr/objects/group_test.rb +46 -0
- data/test/unit/fleakr/objects/image_test.rb +81 -0
- data/test/unit/fleakr/objects/photo_context_test.rb +80 -0
- data/test/unit/fleakr/objects/photo_test.rb +243 -0
- data/test/unit/fleakr/objects/search_test.rb +74 -0
- data/test/unit/fleakr/objects/set_test.rb +82 -0
- data/test/unit/fleakr/objects/tag_test.rb +98 -0
- data/test/unit/fleakr/objects/user_test.rb +91 -0
- data/test/unit/fleakr/support/attribute_test.rb +126 -0
- data/test/unit/fleakr/support/object_test.rb +129 -0
- data/test/unit/fleakr_test.rb +171 -0
- metadata +175 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Api # :nodoc:
|
3
|
+
|
4
|
+
# = UploadRequest
|
5
|
+
#
|
6
|
+
# This implements the upload functionality of the Flickr API which is needed
|
7
|
+
# to create new photos and replace the photo content of existing photos
|
8
|
+
#
|
9
|
+
class UploadRequest
|
10
|
+
|
11
|
+
ENDPOINT_URIS = {
|
12
|
+
:create => 'http://api.flickr.com/services/upload/',
|
13
|
+
:update => 'http://api.flickr.com/services/replace/'
|
14
|
+
}
|
15
|
+
|
16
|
+
attr_reader :parameters, :type
|
17
|
+
|
18
|
+
# Send a request and return a Response object. If an API error occurs, this raises
|
19
|
+
# a Fleakr::ApiError with the reason for the error. See UploadRequest#new for more
|
20
|
+
# details.
|
21
|
+
#
|
22
|
+
def self.with_response!(filename, type = :create, options = {})
|
23
|
+
request = self.new(filename, type, options)
|
24
|
+
response = request.send
|
25
|
+
|
26
|
+
raise(Fleakr::ApiError, "Code: #{response.error.code} - #{response.error.message}") if response.error?
|
27
|
+
|
28
|
+
response
|
29
|
+
end
|
30
|
+
|
31
|
+
# Create a new UploadRequest with the specified filename, type, and options. Type
|
32
|
+
# is one of <tt>:create</tt> or <tt>:update</tt> to specify whether we are saving a new
|
33
|
+
# image or replacing an existing one.
|
34
|
+
#
|
35
|
+
# For a list of available options, see the documentation in Fleakr::Objects::Photo
|
36
|
+
#
|
37
|
+
def initialize(filename, type = :create, options = {})
|
38
|
+
@type = type
|
39
|
+
@options = options
|
40
|
+
|
41
|
+
@parameters = ParameterList.new(upload_options)
|
42
|
+
@parameters << FileParameter.new('photo', filename)
|
43
|
+
end
|
44
|
+
|
45
|
+
# A list of upload options for this upload request (see Fleakr::Api::Option)
|
46
|
+
#
|
47
|
+
def upload_options
|
48
|
+
option_list = @options.map {|key, value| Option.for(key, value) }
|
49
|
+
option_list.inject({}) {|hash, option| hash.merge(option.to_hash)}
|
50
|
+
end
|
51
|
+
|
52
|
+
def headers # :nodoc:
|
53
|
+
{'Content-Type' => "multipart/form-data; boundary=#{self.parameters.boundary}"}
|
54
|
+
end
|
55
|
+
|
56
|
+
def send # :nodoc:
|
57
|
+
response = Net::HTTP.start(endpoint_uri.host, endpoint_uri.port) do |http|
|
58
|
+
logger.info("Sending upload request to: #{endpoint_uri}")
|
59
|
+
logger.debug("Request data:\n#{self.parameters.to_form}")
|
60
|
+
logger.debug("Request headers:\n#{self.headers.inspect}")
|
61
|
+
|
62
|
+
http.post(endpoint_uri.path, self.parameters.to_form, self.headers)
|
63
|
+
end
|
64
|
+
logger.debug("Response data:\n#{response.body}")
|
65
|
+
Response.new(response.body)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def endpoint_uri
|
70
|
+
@endpoint_uri ||= URI.parse(ENDPOINT_URIS[self.type])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Api # :nodoc:
|
3
|
+
|
4
|
+
# = ValueParameter
|
5
|
+
#
|
6
|
+
# A simple name / value parameter for use in API calls
|
7
|
+
#
|
8
|
+
class ValueParameter < Parameter
|
9
|
+
|
10
|
+
attr_reader :value
|
11
|
+
|
12
|
+
# Create a new parameter with the specified name / value pair.
|
13
|
+
#
|
14
|
+
def initialize(name, value, include_in_signature = true)
|
15
|
+
@value = value
|
16
|
+
super(name, include_in_signature)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Generate the query string representation of this parameter.
|
20
|
+
#
|
21
|
+
def to_query
|
22
|
+
"#{self.name}=#{CGI.escape(self.value.to_s)}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Generate the form representation of this parameter.
|
26
|
+
#
|
27
|
+
def to_form
|
28
|
+
"Content-Disposition: form-data; name=\"#{self.name}\"\r\n" +
|
29
|
+
"\r\n" +
|
30
|
+
"#{self.value}\r\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Extract the matching keys from the source hash and return
|
4
|
+
# a new hash with those keys:
|
5
|
+
#
|
6
|
+
# >> h = {:a => 'b', :c => 'd'}
|
7
|
+
# => {:a=>"b", :c=>"d"}
|
8
|
+
# >> h.extract!(:a)
|
9
|
+
# => {:a=>"b"}
|
10
|
+
# >> h
|
11
|
+
# => {:c=>"d"}
|
12
|
+
#
|
13
|
+
def extract!(*keys)
|
14
|
+
value = {}
|
15
|
+
|
16
|
+
keys.each {|k| value.merge!({k => self[k]}) if self.has_key?(k) }
|
17
|
+
keys.each {|k| delete(k) }
|
18
|
+
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'fleakr/objects/authentication_token'
|
2
|
+
require 'fleakr/objects/contact'
|
3
|
+
require 'fleakr/objects/error'
|
4
|
+
require 'fleakr/objects/group'
|
5
|
+
require 'fleakr/objects/image'
|
6
|
+
require 'fleakr/objects/photo_context'
|
7
|
+
require 'fleakr/objects/photo'
|
8
|
+
require 'fleakr/objects/comment'
|
9
|
+
require 'fleakr/objects/tag'
|
10
|
+
require 'fleakr/objects/search'
|
11
|
+
require 'fleakr/objects/set'
|
12
|
+
require 'fleakr/objects/user'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = AuthenticationToken
|
5
|
+
#
|
6
|
+
# This class represents an authentication token used for API calls that
|
7
|
+
# require authentication before they can be used
|
8
|
+
#
|
9
|
+
# == Attributes
|
10
|
+
#
|
11
|
+
# [value] The token value that is used in subsequent API calls
|
12
|
+
# [permissions] The permissions granted to this application (read / write / delete)
|
13
|
+
#
|
14
|
+
class AuthenticationToken
|
15
|
+
|
16
|
+
include Fleakr::Support::Object
|
17
|
+
|
18
|
+
flickr_attribute :value, :from => 'auth/token'
|
19
|
+
flickr_attribute :permissions, :from => 'auth/perms'
|
20
|
+
flickr_attribute :user_id, :from => 'auth/user@nsid'
|
21
|
+
flickr_attribute :user_name, :from => 'auth/user@username'
|
22
|
+
flickr_attribute :full_name, :from => 'auth/user@fullname'
|
23
|
+
|
24
|
+
# Retrieve a full authentication token from the supplied mini-token (e.g. 123-456-789)
|
25
|
+
#
|
26
|
+
def self.from_mini_token(mini_token)
|
27
|
+
from :mini_token, mini_token
|
28
|
+
end
|
29
|
+
|
30
|
+
# Retrieve a full authentication token from the supplied auth_token string
|
31
|
+
# (e.g. 45-76598454353455)
|
32
|
+
#
|
33
|
+
def self.from_auth_token(auth_token)
|
34
|
+
from :auth_token, auth_token
|
35
|
+
end
|
36
|
+
|
37
|
+
# Retrieve a full authentication token from the supplied frob
|
38
|
+
def self.from_frob(frob)
|
39
|
+
from :frob, frob
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.from(thing, value) # :nodoc:
|
43
|
+
api_methods = {
|
44
|
+
:mini_token => 'getFullToken',
|
45
|
+
:auth_token => 'checkToken',
|
46
|
+
:frob => 'getToken'
|
47
|
+
}
|
48
|
+
|
49
|
+
method = "auth.#{api_methods[thing]}"
|
50
|
+
|
51
|
+
parameters = {thing => value, :authenticate? => false}
|
52
|
+
response = Fleakr::Api::MethodRequest.with_response!(method, parameters)
|
53
|
+
|
54
|
+
self.new(response.body)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Comment
|
5
|
+
#
|
6
|
+
# This class represents a comment that can be associated with a single photo or an
|
7
|
+
# entire photoset.
|
8
|
+
#
|
9
|
+
# == Attributes
|
10
|
+
#
|
11
|
+
# [id] The unique identifier for this comment
|
12
|
+
# [url] The direct URL / permalink to reference this comment
|
13
|
+
# [body] The comment itself - also available with <tt>to_s</tt>
|
14
|
+
#
|
15
|
+
class Comment
|
16
|
+
|
17
|
+
include Fleakr::Support::Object
|
18
|
+
|
19
|
+
find_all :by_photo_id, :call => 'photos.comments.getList', :path => 'comments/comment'
|
20
|
+
find_all :by_set_id, :using => :photoset_id, :call => 'photosets.comments.getList', :path => 'comments/comment'
|
21
|
+
|
22
|
+
flickr_attribute :id
|
23
|
+
flickr_attribute :author_id, :from => '@author'
|
24
|
+
flickr_attribute :created, :from => '@datecreate'
|
25
|
+
flickr_attribute :url, :from => '@permalink'
|
26
|
+
flickr_attribute :body, :from => '.'
|
27
|
+
|
28
|
+
# The user who supplied the comment. See Fleakr::Objects::User for more information
|
29
|
+
#
|
30
|
+
def author
|
31
|
+
@author ||= User.find_by_id(author_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
# When was this comment created?
|
35
|
+
#
|
36
|
+
def created_at
|
37
|
+
Time.at(created.to_i)
|
38
|
+
end
|
39
|
+
|
40
|
+
# The contents of the comment - also available as <tt>body</tt>
|
41
|
+
#
|
42
|
+
def to_s
|
43
|
+
body
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
class Contact # :nodoc:
|
4
|
+
|
5
|
+
include Fleakr::Support::Object
|
6
|
+
|
7
|
+
flickr_attribute :id, :from => '@nsid'
|
8
|
+
flickr_attribute :username
|
9
|
+
flickr_attribute :icon_server, :from => '@iconserver'
|
10
|
+
flickr_attribute :icon_farm, :from => '@iconfarm'
|
11
|
+
|
12
|
+
# Retrieve a list of contacts for the specified user ID and return an initialized
|
13
|
+
# collection of #User objects
|
14
|
+
def self.find_all_by_user_id(user_id)
|
15
|
+
response = Fleakr::Api::MethodRequest.with_response!('contacts.getPublicList', :user_id => user_id)
|
16
|
+
(response.body/'contacts/contact').map {|c| Contact.new(c).to_user }
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_user
|
20
|
+
user = User.new
|
21
|
+
self.class.attributes.each do |attribute|
|
22
|
+
attribute_name = attribute.name
|
23
|
+
user.send("#{attribute.name}=".to_sym, self.send(attribute.name))
|
24
|
+
end
|
25
|
+
|
26
|
+
user
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
# = Error
|
4
|
+
#
|
5
|
+
# == Accessors
|
6
|
+
#
|
7
|
+
# This class is a simple wrapper for the error response that the API returns. There are
|
8
|
+
# a couple of attributes:
|
9
|
+
#
|
10
|
+
# [code] The error code as described in the documentation
|
11
|
+
# [message] The associated error message
|
12
|
+
#
|
13
|
+
class Error
|
14
|
+
|
15
|
+
include Fleakr::Support::Object
|
16
|
+
|
17
|
+
flickr_attribute :code, :from => 'err@code'
|
18
|
+
flickr_attribute :message, :from => 'err@msg'
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Group
|
5
|
+
#
|
6
|
+
# == Accessors
|
7
|
+
#
|
8
|
+
# [id] This group's ID
|
9
|
+
# [name] The name of the group
|
10
|
+
#
|
11
|
+
# == Associations
|
12
|
+
#
|
13
|
+
# [photos] The photos that are in this group
|
14
|
+
#
|
15
|
+
class Group
|
16
|
+
|
17
|
+
include Fleakr::Support::Object
|
18
|
+
|
19
|
+
flickr_attribute :id, :from => '@nsid'
|
20
|
+
flickr_attribute :name
|
21
|
+
flickr_attribute :adult_flag, :from => '@eighteenplus'
|
22
|
+
|
23
|
+
find_all :by_user_id, :call => 'people.getPublicGroups', :path => 'groups/group'
|
24
|
+
|
25
|
+
has_many :photos
|
26
|
+
|
27
|
+
scoped_search
|
28
|
+
|
29
|
+
# Is this group adult-only? (e.g. only 18+ allowed to view)
|
30
|
+
def adult?
|
31
|
+
(adult_flag == '1')
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects
|
3
|
+
|
4
|
+
# = Image
|
5
|
+
#
|
6
|
+
# This class wraps the functionality for saving remote images to disk. It's called
|
7
|
+
# by the Fleakr::Objects::Photo class to save an image with a specific size and would
|
8
|
+
# typically never be called directly.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# user = Fleakr.user('brownout')
|
13
|
+
# user.photos.first.small.save_to('/tmp')
|
14
|
+
#
|
15
|
+
# == Attributes
|
16
|
+
#
|
17
|
+
# [size] The name of this image's size (e.g. Square, Large, etc...)
|
18
|
+
# [width] The width of this image
|
19
|
+
# [height] The height of this image
|
20
|
+
# [url] The direct URL for this image
|
21
|
+
# [page] The page on Flickr that represents this photo
|
22
|
+
#
|
23
|
+
class Image
|
24
|
+
|
25
|
+
include Fleakr::Support::Object
|
26
|
+
|
27
|
+
flickr_attribute :width, :height
|
28
|
+
flickr_attribute :size, :from => '@label'
|
29
|
+
flickr_attribute :url, :from => '@source'
|
30
|
+
flickr_attribute :page, :from => '@url'
|
31
|
+
|
32
|
+
find_all :by_photo_id, :call => 'photos.getSizes', :path => 'sizes/size'
|
33
|
+
|
34
|
+
# The filename portion of the image (without the full URL)
|
35
|
+
def filename
|
36
|
+
self.url.match(/([^\/]+)$/)[1]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Save this image to the specified directory or file. If the target is a
|
40
|
+
# directory, the file will be created with the original filename from Flickr.
|
41
|
+
# If the target is a file, it will be saved with the specified name. In the
|
42
|
+
# case that the target file already exists, this method will overwrite it.
|
43
|
+
def save_to(target, prefix = nil)
|
44
|
+
destination = File.directory?(target) ? "#{target}/#{prefix}#{self.filename}" : "#{target}"
|
45
|
+
File.open(destination, 'w') {|f| f << Net::HTTP.get(URI.parse(self.url)) }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Photo
|
5
|
+
#
|
6
|
+
# Handles both the retrieval of Photo objects from various associations (e.g. User / Set) as
|
7
|
+
# well as the ability to upload images to the Flickr site.
|
8
|
+
#
|
9
|
+
# == Attributes
|
10
|
+
#
|
11
|
+
# [id] The ID for this photo
|
12
|
+
# [title] The title of this photo
|
13
|
+
# [description] The description of this photo
|
14
|
+
# [secret] This photo's secret (used for sharing photo without permissions checking)
|
15
|
+
# [comment_count] Count of the comments attached to this photo
|
16
|
+
# [url] This photo's page on Flickr
|
17
|
+
# [square] The tiny square representation of this photo
|
18
|
+
# [thumbnail] The thumbnail for this photo
|
19
|
+
# [small] The small representation of this photo
|
20
|
+
# [medium] The medium representation of this photo
|
21
|
+
# [large] The large representation of this photo
|
22
|
+
# [original] The original photo
|
23
|
+
# [previous] The previous photo based on the current context
|
24
|
+
# [next] The next photo based on the current context
|
25
|
+
#
|
26
|
+
# == Associations
|
27
|
+
#
|
28
|
+
# [images] The underlying images for this photo.
|
29
|
+
# [tags] The tags for this photo.
|
30
|
+
# [comments] The comments associated with this photo
|
31
|
+
#
|
32
|
+
class Photo
|
33
|
+
|
34
|
+
# Available sizes for this photo
|
35
|
+
SIZES = [:square, :thumbnail, :small, :medium, :large, :original]
|
36
|
+
|
37
|
+
include Fleakr::Support::Object
|
38
|
+
extend Forwardable
|
39
|
+
|
40
|
+
def_delegators :context, :next, :previous
|
41
|
+
|
42
|
+
flickr_attribute :id, :from => ['@id', 'photoid']
|
43
|
+
flickr_attribute :title, :description, :secret, :posted, :taken, :url
|
44
|
+
flickr_attribute :farm_id, :from => '@farm'
|
45
|
+
flickr_attribute :server_id, :from => '@server'
|
46
|
+
flickr_attribute :owner_id, :from => ['@owner', 'owner@nsid']
|
47
|
+
flickr_attribute :updated, :from => '@lastupdate'
|
48
|
+
flickr_attribute :comment_count, :from => 'comments'
|
49
|
+
|
50
|
+
# TODO:
|
51
|
+
# * visibility
|
52
|
+
# * editability
|
53
|
+
# * usage
|
54
|
+
|
55
|
+
find_all :by_set_id, :using => :photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
|
56
|
+
find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
|
57
|
+
find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
|
58
|
+
|
59
|
+
find_one :by_id, :using => :photo_id, :call => 'photos.getInfo'
|
60
|
+
|
61
|
+
lazily_load :posted, :taken, :updated, :comment_count, :url, :description, :with => :load_info
|
62
|
+
|
63
|
+
has_many :images, :tags, :comments
|
64
|
+
|
65
|
+
# Upload the photo specified by <tt>filename</tt> to the user's Flickr account. When uploading,
|
66
|
+
# there are several options available (none are required):
|
67
|
+
#
|
68
|
+
# [:title] The title for this photo. Any string is allowed.
|
69
|
+
# [:description] The description for this photo. Any string is allowed.
|
70
|
+
# [:tags] A collection of tags for this photo. This can be a string or array of strings.
|
71
|
+
# [:viewable_by] Who can view this photo? Acceptable values are one of <tt>:everyone</tt>,
|
72
|
+
# <tt>:friends</tt> or <tt>:family</tt>. This can also take an array of values
|
73
|
+
# (e.g. <tt>[:friends, :family]</tt>) to make it viewable by friends and family.
|
74
|
+
# [:level] The safety level of this photo. Acceptable values are one of <tt>:safe</tt>,
|
75
|
+
# <tt>:moderate</tt>, or <tt>:restricted</tt>.
|
76
|
+
# [:type] The type of image this is. Acceptable values are one of <tt>:photo</tt>,
|
77
|
+
# <tt>:screenshot</tt>, or <tt>:other</tt>.
|
78
|
+
# [:hide?] Should this photo be hidden from public searches? Takes a boolean.
|
79
|
+
#
|
80
|
+
def self.upload(filename, options = {})
|
81
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :create, options)
|
82
|
+
photo = Photo.new(response.body)
|
83
|
+
Photo.find_by_id(photo.id)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Replace the current photo's image with the one specified by filename. This
|
87
|
+
# call requires authentication.
|
88
|
+
#
|
89
|
+
def replace_with(filename)
|
90
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :update, :photo_id => self.id)
|
91
|
+
self.populate_from(response.body)
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
# TODO: Refactor this to remove duplication w/ User#load_info - possibly in the lazily_load class method
|
96
|
+
def load_info # :nodoc:
|
97
|
+
response = Fleakr::Api::MethodRequest.with_response!('photos.getInfo', :photo_id => self.id)
|
98
|
+
self.populate_from(response.body)
|
99
|
+
end
|
100
|
+
|
101
|
+
def context # :nodoc:
|
102
|
+
@context ||= begin
|
103
|
+
response = Fleakr::Api::MethodRequest.with_response!('photos.getContext', :photo_id => self.id)
|
104
|
+
PhotoContext.new(response.body)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# The user who uploaded this photo. See Fleakr::Objects::User for additional information.
|
109
|
+
#
|
110
|
+
def owner
|
111
|
+
@owner ||= User.find_by_id(owner_id)
|
112
|
+
end
|
113
|
+
|
114
|
+
# When was this photo posted?
|
115
|
+
#
|
116
|
+
def posted_at
|
117
|
+
Time.at(posted.to_i)
|
118
|
+
end
|
119
|
+
|
120
|
+
# When was this photo taken?
|
121
|
+
#
|
122
|
+
def taken_at
|
123
|
+
Time.parse(taken)
|
124
|
+
end
|
125
|
+
|
126
|
+
# When was this photo last updated? This includes addition of tags and other metadata.
|
127
|
+
#
|
128
|
+
def updated_at
|
129
|
+
Time.at(updated.to_i)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Create methods to access image sizes by name
|
133
|
+
SIZES.each do |size|
|
134
|
+
define_method(size) do
|
135
|
+
images_by_size[size]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
def images_by_size
|
141
|
+
image_sizes = SIZES.inject({}) {|l,o| l.merge(o => nil)}
|
142
|
+
self.images.inject(image_sizes) {|l,o| l.merge!(o.size.downcase.to_sym => o) }
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|