fleakr 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +149 -0
- data/Rakefile +40 -0
- data/lib/fleakr/api/request.rb +58 -0
- data/lib/fleakr/api/response.rb +35 -0
- data/lib/fleakr/objects/contact.rb +31 -0
- data/lib/fleakr/objects/error.rb +22 -0
- data/lib/fleakr/objects/group.rb +26 -0
- data/lib/fleakr/objects/image.rb +51 -0
- data/lib/fleakr/objects/photo.rb +55 -0
- data/lib/fleakr/objects/search.rb +33 -0
- data/lib/fleakr/objects/set.rb +45 -0
- data/lib/fleakr/objects/user.rb +106 -0
- data/lib/fleakr/support/attribute.rb +28 -0
- data/lib/fleakr/support/object.rb +88 -0
- data/lib/fleakr/version.rb +13 -0
- data/lib/fleakr.rb +74 -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.getSizes.xml +10 -0
- data/test/fixtures/photos.search.xml +7 -0
- data/test/fixtures/photosets.getList.xml +13 -0
- data/test/fixtures/photosets.getPhotos.xml +7 -0
- data/test/test_helper.rb +123 -0
- data/test/unit/fleakr/api/request_test.rb +93 -0
- data/test/unit/fleakr/api/response_test.rb +49 -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 +31 -0
- data/test/unit/fleakr/objects/image_test.rb +76 -0
- data/test/unit/fleakr/objects/photo_test.rb +101 -0
- data/test/unit/fleakr/objects/search_test.rb +74 -0
- data/test/unit/fleakr/objects/set_test.rb +71 -0
- data/test/unit/fleakr/objects/user_test.rb +104 -0
- data/test/unit/fleakr/support/attribute_test.rb +68 -0
- data/test/unit/fleakr/support/object_test.rb +95 -0
- data/test/unit/fleakr_test.rb +44 -0
- metadata +123 -0
data/README.rdoc
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
= Fleakr
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
A teeny tiny gem to interface with Flickr photostreams
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
=== Stable
|
10
|
+
|
11
|
+
sudo gem install fleakr
|
12
|
+
|
13
|
+
=== Bleeding Edge
|
14
|
+
|
15
|
+
sudo gem install reagent-fleakr --source=http://gems.github.com
|
16
|
+
|
17
|
+
Or ...
|
18
|
+
|
19
|
+
$ git clone git://github.com/reagent/fleakr.git
|
20
|
+
$ cd fleakr
|
21
|
+
$ rake gem && sudo gem install pkg/fleakr-<version>.gem
|
22
|
+
|
23
|
+
== Usage
|
24
|
+
|
25
|
+
Before doing anything, require the library:
|
26
|
+
|
27
|
+
>> require 'rubygems'
|
28
|
+
>> require 'fleakr'
|
29
|
+
|
30
|
+
Then, set your API key (only need to do this once per session):
|
31
|
+
|
32
|
+
>> Fleakr.api_key = '<your api key here>'
|
33
|
+
|
34
|
+
Find a user by username:
|
35
|
+
|
36
|
+
>> user = Fleakr.user('the decapitator')
|
37
|
+
=> #<Fleakr::Objects::User:0x692648 @username="the decapitator", @id="21775151@N06">
|
38
|
+
|
39
|
+
Or by email:
|
40
|
+
|
41
|
+
>> user = Fleakr.user('user@host.com')
|
42
|
+
=> #<Fleakr::Objects::User:0x11f484c @username="bckspcr", @id="84481630@N00">
|
43
|
+
|
44
|
+
Once you have a user, you can find his associated sets:
|
45
|
+
|
46
|
+
>> user.sets
|
47
|
+
=> [#<Fleakr::Objects::Set:0x671358 @title="The Decapitator", @description="">,
|
48
|
+
#<Fleakr::Objects::Set:0x66d898 @title="londonpaper hijack", ...
|
49
|
+
|
50
|
+
Or contacts:
|
51
|
+
|
52
|
+
>> user.contacts.first
|
53
|
+
=> #<Fleakr::Objects::User:0x19039bc @username=".schill",
|
54
|
+
@id="12289718@N00", @icon_farm="1", @icon_server="4">
|
55
|
+
|
56
|
+
Or groups if you would like:
|
57
|
+
|
58
|
+
>> user.groups
|
59
|
+
=> [#<Fleakr::Objects::Group:0x11f2330 ...,
|
60
|
+
#<Fleakr::Objects::Group:0x11f2308 ...
|
61
|
+
>> user.groups.first.name
|
62
|
+
=> "Rural Decay"
|
63
|
+
>> user.groups.first.id
|
64
|
+
=> "14581414@N00"
|
65
|
+
|
66
|
+
Groups also contain photos:
|
67
|
+
|
68
|
+
>> user.groups.last.photos.first.title
|
69
|
+
=> "Welcome To The Machine"
|
70
|
+
|
71
|
+
When accessing a set, you can also grab all the photos that are in that set:
|
72
|
+
|
73
|
+
>> user.sets.first
|
74
|
+
=> #<Fleakr::Objects::Set:0x1195bbc @title="The Decapitator", @id="72157603480986566", @description="">
|
75
|
+
>> user.sets.first.photos.first
|
76
|
+
=> #<Fleakr::Objects::Photo:0x1140108 ... >
|
77
|
+
>> user.sets.first.photos.first.title
|
78
|
+
=> "Untitled1"
|
79
|
+
|
80
|
+
If a photo interests you, save it down to a directory of your choosing:
|
81
|
+
|
82
|
+
>> user.sets.first.photos.first.small.save_to('/tmp')
|
83
|
+
=> #<File:/tmp/2117922283_715587b2cb_m.jpg (closed)>
|
84
|
+
|
85
|
+
If you can't decide on a photo and would rather just save the whole set, specify the target directory
|
86
|
+
and the size of the images you're interested in:
|
87
|
+
|
88
|
+
>> user.sets.first.save_to('/tmp', :square)
|
89
|
+
=> [#<Fleakr::Objects::Photo:0x1187a1c @secret="715587b2cb" ...
|
90
|
+
>> Dir["/tmp/#{user.sets.first.title}/*.jpg"].map
|
91
|
+
=> ["/tmp/The Decapitator/2117919621_8b2d601bff_s.jpg",
|
92
|
+
"/tmp/The Decapitator/2117921045_5fb15eff90_s.jpg",
|
93
|
+
"/tmp/The Decapitator/2117922283_715587b2cb_s.jpg", ...
|
94
|
+
|
95
|
+
If you would prefer to just search photos, you can do that with search text:
|
96
|
+
|
97
|
+
>> photos = Fleakr.search('ponies!!')
|
98
|
+
=> [#<Fleakr::Objects::Photo:0x11f4e64 @title="hiroshima atomic garden", @id="3078234390">,
|
99
|
+
#<Fleakr::Objects::Photo:0x11f4928 @title="PONYLOV", @id="3077360853">, ...
|
100
|
+
>> photos.first.title
|
101
|
+
=> "hiroshima atomic garden"
|
102
|
+
|
103
|
+
You can also search based on tags:
|
104
|
+
|
105
|
+
>> photos = Fleakr.search(:tags => 'macro')
|
106
|
+
>> photos.first.title
|
107
|
+
=> "Demure"
|
108
|
+
>> photos.first.id
|
109
|
+
=> "3076049945"
|
110
|
+
|
111
|
+
Searches can also be scoped to other entities in the system (namely Users and Groups):
|
112
|
+
|
113
|
+
>> user.groups.first.search('awesome')
|
114
|
+
=> [#<Fleakr::Objects::Photo:0x18cb4cc @server_id="2012", @id="2181921273",
|
115
|
+
@farm_id="3", @title="", @secret="634eda7521">, ...
|
116
|
+
>> user.search('serpent')
|
117
|
+
=> [#<Fleakr::Objects::Photo:0x18a6960 @server_id="41", @id="81370156",
|
118
|
+
@farm_id="1", @title="Clear and Serpent Danger", @secret="013091582a">]
|
119
|
+
|
120
|
+
== TODO
|
121
|
+
|
122
|
+
* Implement remaining bits of person, photoset, and photo-releated APIs
|
123
|
+
* Provide a better searching interface
|
124
|
+
* Lazily load attributes for objects that need to be accessed via secondary API call
|
125
|
+
|
126
|
+
== License
|
127
|
+
|
128
|
+
Copyright (c) 2008 Patrick Reagan (reaganpr@gmail.com)
|
129
|
+
|
130
|
+
Permission is hereby granted, free of charge, to any person
|
131
|
+
obtaining a copy of this software and associated documentation
|
132
|
+
files (the "Software"), to deal in the Software without
|
133
|
+
restriction, including without limitation the rights to use,
|
134
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
135
|
+
copies of the Software, and to permit persons to whom the
|
136
|
+
Software is furnished to do so, subject to the following
|
137
|
+
conditions:
|
138
|
+
|
139
|
+
The above copyright notice and this permission notice shall be
|
140
|
+
included in all copies or substantial portions of the Software.
|
141
|
+
|
142
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
143
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
144
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
145
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
146
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
147
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
148
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
149
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require 'lib/fleakr/version'
|
6
|
+
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'fleakr'
|
11
|
+
s.version = Fleakr::Version.to_s
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.extra_rdoc_files = %w(README.rdoc)
|
14
|
+
s.rdoc_options = %w(--main README.rdoc)
|
15
|
+
s.summary = "A teeny tiny gem to interface with Flickr photostreams"
|
16
|
+
s.author = 'Patrick Reagan'
|
17
|
+
s.email = 'reaganpr@gmail.com'
|
18
|
+
s.homepage = 'http://sneaq.net'
|
19
|
+
s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
|
20
|
+
|
21
|
+
s.add_dependency('hpricot', '~> 0.6.0')
|
22
|
+
s.add_dependency('activesupport', '~> 2.2.0')
|
23
|
+
end
|
24
|
+
|
25
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
26
|
+
pkg.gem_spec = spec
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::TestTask.new do |t|
|
30
|
+
t.libs << 'test'
|
31
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
32
|
+
t.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Generate the gemspec to serve this Gem from Github'
|
36
|
+
task :github do
|
37
|
+
file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
|
38
|
+
File.open(file, 'w') {|f| f << spec.to_ruby }
|
39
|
+
puts "Created gemspec: #{file}"
|
40
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Api # :nodoc:
|
3
|
+
|
4
|
+
# = Request
|
5
|
+
#
|
6
|
+
# Performs requests against the Flickr API and returns response objects (Flickr::Api::Response)
|
7
|
+
# that contain Hpricot documents for further parsing and inspection. This class is used internally
|
8
|
+
# in all the defined model objects.
|
9
|
+
#
|
10
|
+
class Request
|
11
|
+
|
12
|
+
# Generic catch-all exception for any API errors
|
13
|
+
class ApiError < StandardError; end
|
14
|
+
|
15
|
+
# Makes a request to the Flickr API and returns a valid Response object. If
|
16
|
+
# there are errors on the response it will rais an ApiError exception
|
17
|
+
def self.with_response!(method, additional_parameters = {})
|
18
|
+
request = Request.new(method, additional_parameters)
|
19
|
+
response = request.send
|
20
|
+
|
21
|
+
raise(ApiError, "Code: #{response.error.code} - #{response.error.message}") if response.error?
|
22
|
+
|
23
|
+
response
|
24
|
+
end
|
25
|
+
|
26
|
+
# Create a new request for the specified API method and pass along any additional
|
27
|
+
# parameters. The Flickr API uses namespacing for its methods - this is optional
|
28
|
+
# when calling this method.
|
29
|
+
#
|
30
|
+
# This must be called after initializing the library with the required API key
|
31
|
+
# see (#Fleakr.api_key=)
|
32
|
+
def initialize(method, additional_parameters = {})
|
33
|
+
method = method.sub(/^(flickr\.)?/, 'flickr.')
|
34
|
+
|
35
|
+
default_parameters = {:api_key => Fleakr.api_key, :method => method}
|
36
|
+
@parameters = default_parameters.merge(additional_parameters)
|
37
|
+
end
|
38
|
+
|
39
|
+
def send # :nodoc:
|
40
|
+
Response.new(Net::HTTP.get(endpoint_uri))
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def endpoint_uri
|
45
|
+
uri = URI.parse('http://api.flickr.com/services/rest/')
|
46
|
+
uri.query = query_parameters
|
47
|
+
uri
|
48
|
+
end
|
49
|
+
|
50
|
+
def query_parameters
|
51
|
+
@parameters.map {|key,value| "#{key}=#{CGI.escape(value)}" }.join('&')
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Api
|
3
|
+
|
4
|
+
# = Response
|
5
|
+
#
|
6
|
+
# Response objects contain Hpricot documents that are traversed and parsed by
|
7
|
+
# the model objects. This class is never called directly but is instantiated
|
8
|
+
# during the request cycle (see: Fleakr::Api::Request.with_response!)
|
9
|
+
#
|
10
|
+
class Response
|
11
|
+
|
12
|
+
# Creates a new response from a raw XML string returned from a Request
|
13
|
+
def initialize(response_xml)
|
14
|
+
@response_xml = response_xml
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return a document-based representation of the XML contained in the
|
18
|
+
# API response. This is an Hpricot document object
|
19
|
+
def body
|
20
|
+
@body ||= Hpricot.XML(@response_xml)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Did the response from the API contain errors?
|
24
|
+
def error?
|
25
|
+
(self.body/'rsp').attr('stat') != 'ok'
|
26
|
+
end
|
27
|
+
|
28
|
+
# Access the API error if one exists
|
29
|
+
def error
|
30
|
+
Fleakr::Objects::Error.new(self.body) if self.error?
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
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, :attribute => 'nsid'
|
8
|
+
flickr_attribute :username, :attribute => 'username'
|
9
|
+
flickr_attribute :icon_server, :attribute => 'iconserver'
|
10
|
+
flickr_attribute :icon_farm, :attribute => '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::Request.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, :xpath => 'rsp/err', :attribute => 'code'
|
18
|
+
flickr_attribute :message, :xpath => 'rsp/err', :attribute => 'msg'
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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
|
+
class Group
|
12
|
+
|
13
|
+
include Fleakr::Support::Object
|
14
|
+
|
15
|
+
flickr_attribute :id, :attribute => 'nsid'
|
16
|
+
flickr_attribute :name, :attribute => 'name'
|
17
|
+
|
18
|
+
find_all :by_user_id, :call => 'people.getPublicGroups', :path => 'groups/group'
|
19
|
+
|
20
|
+
has_many :photos
|
21
|
+
|
22
|
+
scoped_search
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
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 :size, :attribute => :label
|
28
|
+
flickr_attribute :width, :attribute => :width
|
29
|
+
flickr_attribute :height, :attribute => :height
|
30
|
+
flickr_attribute :url, :attribute => :source
|
31
|
+
flickr_attribute :page, :attribute => :url
|
32
|
+
|
33
|
+
find_all :by_photo_id, :call => 'photos.getSizes', :path => 'sizes/size'
|
34
|
+
|
35
|
+
# The filename portion of the image (without the full URL)
|
36
|
+
def filename
|
37
|
+
self.url.match(/([^\/]+)$/)[1]
|
38
|
+
end
|
39
|
+
|
40
|
+
# Save this image to the specified directory or file. If the target is a
|
41
|
+
# directory, the file will be created with the original filename from Flickr.
|
42
|
+
# If the target is a file, it will be saved with the specified name. In the
|
43
|
+
# case that the target file already exists, this method will overwrite it.
|
44
|
+
def save_to(target)
|
45
|
+
destination = File.directory?(target) ? "#{target}/#{self.filename}" : "#{target}"
|
46
|
+
File.open(destination, 'w') {|f| f << Net::HTTP.get(URI.parse(self.url)) }
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Photo
|
5
|
+
#
|
6
|
+
# == Attributes
|
7
|
+
#
|
8
|
+
# [id] The ID for this photo
|
9
|
+
# [title] The title of this photo
|
10
|
+
# [square] The tiny square representation of this photo
|
11
|
+
# [thumbnail] The thumbnail for this photo
|
12
|
+
# [small] The small representation of this photo
|
13
|
+
# [medium] The medium representation of this photo
|
14
|
+
# [large] The large representation of this photo
|
15
|
+
# [original] The original photo
|
16
|
+
#
|
17
|
+
# == Associations
|
18
|
+
#
|
19
|
+
# [images] The underlying images for this photo.
|
20
|
+
#
|
21
|
+
class Photo
|
22
|
+
|
23
|
+
# Available sizes for this photo
|
24
|
+
SIZES = [:square, :thumbnail, :small, :medium, :large, :original]
|
25
|
+
|
26
|
+
include Fleakr::Support::Object
|
27
|
+
|
28
|
+
flickr_attribute :title, :attribute => 'title'
|
29
|
+
flickr_attribute :id, :attribute => 'id'
|
30
|
+
flickr_attribute :farm_id, :attribute => 'farm'
|
31
|
+
flickr_attribute :server_id, :attribute => 'server'
|
32
|
+
flickr_attribute :secret, :attribute => 'secret'
|
33
|
+
|
34
|
+
find_all :by_photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
|
35
|
+
find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
|
36
|
+
find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
|
37
|
+
|
38
|
+
has_many :images
|
39
|
+
|
40
|
+
# Create methods to access image sizes by name
|
41
|
+
SIZES.each do |size|
|
42
|
+
define_method(size) do
|
43
|
+
images_by_size[size]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def images_by_size
|
49
|
+
image_sizes = SIZES.inject({}) {|l,o| l.merge(o => nil)}
|
50
|
+
self.images.inject(image_sizes) {|l,o| l.merge!(o.size.downcase.to_sym => o) }
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
class Search
|
4
|
+
|
5
|
+
# Create a new search
|
6
|
+
def initialize(search_options)
|
7
|
+
@search_options = search_options
|
8
|
+
end
|
9
|
+
|
10
|
+
# Retrieve search results from the API
|
11
|
+
def results
|
12
|
+
if @results.nil?
|
13
|
+
response = Fleakr::Api::Request.with_response!('photos.search', parameters)
|
14
|
+
@results = (response.body/'rsp/photos/photo').map do |flickr_photo|
|
15
|
+
Photo.new(flickr_photo)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@results
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def tag_list
|
23
|
+
Array(@search_options[:tags]).join(',')
|
24
|
+
end
|
25
|
+
|
26
|
+
def parameters
|
27
|
+
@search_options.merge!(:tags => tag_list) if tag_list.length > 0
|
28
|
+
@search_options
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = Set
|
5
|
+
#
|
6
|
+
# == Attributes
|
7
|
+
#
|
8
|
+
# [id] The ID for this photoset
|
9
|
+
# [title] The title of this photoset
|
10
|
+
# [description] The description of this set
|
11
|
+
#
|
12
|
+
# == Associations
|
13
|
+
#
|
14
|
+
# [photos] The collection of photos for this set. See Fleakr::Objects::Photo
|
15
|
+
#
|
16
|
+
class Set
|
17
|
+
|
18
|
+
include Fleakr::Support::Object
|
19
|
+
|
20
|
+
has_many :photos, :using => :photoset_id
|
21
|
+
|
22
|
+
flickr_attribute :id, :attribute => 'id'
|
23
|
+
flickr_attribute :title
|
24
|
+
flickr_attribute :description
|
25
|
+
|
26
|
+
find_all :by_user_id, :call => 'photosets.getList', :path => 'photosets/photoset'
|
27
|
+
|
28
|
+
# Save all photos in this set to the specified directory using the specified size. Allowed
|
29
|
+
# Sizes include <tt>:square</tt>, <tt>:small</tt>, <tt>:thumbnail</tt>, <tt>:medium</tt>,
|
30
|
+
# <tt>:large</tt>, and <tt>:original</tt>. When saving the set, this # method will create
|
31
|
+
# a subdirectory based on the set's title.
|
32
|
+
#
|
33
|
+
def save_to(path, size)
|
34
|
+
target = "#{path}/#{self.title}"
|
35
|
+
FileUtils.mkdir(target) unless File.exist?(target)
|
36
|
+
|
37
|
+
self.photos.each do |photo|
|
38
|
+
image = photo.send(size)
|
39
|
+
image.save_to(target) unless image.nil?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Objects # :nodoc:
|
3
|
+
|
4
|
+
# = User
|
5
|
+
#
|
6
|
+
# == Accessors
|
7
|
+
#
|
8
|
+
# This class maps directly onto the flickr.people.* API methods and provides the following attributes
|
9
|
+
# for a user:
|
10
|
+
#
|
11
|
+
# [id] The ID for this user (also referred to as the NSID in the API docs)
|
12
|
+
# [username] This user's username
|
13
|
+
# [name] This user's full name (if entered)
|
14
|
+
# [photos_url] The direct URL to this user's photostream
|
15
|
+
# [profile_url] The direct URL to this user's profile
|
16
|
+
# [photos_count] The number of photos that this user has uploaded
|
17
|
+
# [icon_url] This user's buddy icon (or a default one if an icon wasn't uploaded)
|
18
|
+
# [pro?] Does this user have a pro account?
|
19
|
+
# [admin?] Is this user an admin?
|
20
|
+
#
|
21
|
+
# == Associations
|
22
|
+
#
|
23
|
+
# The User class is pretty central to many of the other data available across the system, so there are a
|
24
|
+
# few associations available to a user:
|
25
|
+
#
|
26
|
+
# [sets] A list of this user's public sets (newest first). See Fleakr::Objects::Set for more information.
|
27
|
+
# [groups] A list of this user's public groups. See Fleakr::Objects::Group.
|
28
|
+
# [photos] A list of this user's public photos (newest first). See Fleakr::Objects::Photo.
|
29
|
+
# [contacts] A list of this user's contacts - these are simply User objects
|
30
|
+
#
|
31
|
+
# == Examples
|
32
|
+
#
|
33
|
+
# Access to a specific user is typically done through the Fleakr.user method:
|
34
|
+
#
|
35
|
+
# user = Fleakr.user('brownout')
|
36
|
+
# user.id
|
37
|
+
# user.username
|
38
|
+
# user.sets
|
39
|
+
# user.contacts
|
40
|
+
#
|
41
|
+
class User
|
42
|
+
|
43
|
+
include Fleakr::Support::Object
|
44
|
+
|
45
|
+
def self.lazily_load(*attributes)
|
46
|
+
options = attributes.extract_options!
|
47
|
+
|
48
|
+
attributes.each do |attribute|
|
49
|
+
class_eval <<-CODE
|
50
|
+
def #{attribute}_with_loading
|
51
|
+
self.send(:#{options[:with]}) if @#{attribute}.nil?
|
52
|
+
#{attribute}_without_loading
|
53
|
+
end
|
54
|
+
alias_method_chain :#{attribute}, :loading
|
55
|
+
CODE
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
flickr_attribute :id, :xpath => 'rsp/user', :attribute => 'nsid'
|
60
|
+
flickr_attribute :username, :xpath => 'rsp/user/username'
|
61
|
+
flickr_attribute :name, :xpath => 'rsp/person/realname'
|
62
|
+
flickr_attribute :photos_url, :xpath => 'rsp/person/photosurl'
|
63
|
+
flickr_attribute :profile_url, :xpath => 'rsp/person/profileurl'
|
64
|
+
flickr_attribute :photos_count, :xpath => 'rsp/person/photos/count'
|
65
|
+
flickr_attribute :icon_server, :xpath => 'rsp/person', :attribute => 'iconserver'
|
66
|
+
flickr_attribute :icon_farm, :xpath => 'rsp/person', :attribute => 'iconfarm'
|
67
|
+
flickr_attribute :pro, :xpath => 'rsp/person', :attribute => 'ispro'
|
68
|
+
flickr_attribute :admin, :xpath => 'rsp/person', :attribute => 'isadmin'
|
69
|
+
|
70
|
+
has_many :sets, :groups, :photos, :contacts
|
71
|
+
|
72
|
+
find_one :by_username, :call => 'people.findByUsername'
|
73
|
+
find_one :by_email, :using => :find_email, :call => 'people.findByEmail'
|
74
|
+
|
75
|
+
lazily_load :name, :photos_url, :profile_url, :photos_count, :with => :load_info
|
76
|
+
lazily_load :icon_server, :icon_farm, :pro, :admin, :with => :load_info
|
77
|
+
|
78
|
+
scoped_search
|
79
|
+
|
80
|
+
# Is this a pro account?
|
81
|
+
def pro?
|
82
|
+
(self.pro.to_i == 0) ? false : true
|
83
|
+
end
|
84
|
+
|
85
|
+
# Is this user an admin?
|
86
|
+
def admin?
|
87
|
+
(self.admin.to_i == 0) ? false : true
|
88
|
+
end
|
89
|
+
|
90
|
+
# This user's buddy icon
|
91
|
+
def icon_url
|
92
|
+
if self.icon_server.to_i > 0
|
93
|
+
"http://farm#{self.icon_farm}.static.flickr.com/#{self.icon_server}/buddyicons/#{self.id}.jpg"
|
94
|
+
else
|
95
|
+
'http://www.flickr.com/images/buddyicon.jpg'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_info # :nodoc:
|
100
|
+
response = Fleakr::Api::Request.with_response!('people.getInfo', :user_id => self.id)
|
101
|
+
self.populate_from(response.body)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Fleakr
|
2
|
+
module Support # :nodoc:all
|
3
|
+
class Attribute
|
4
|
+
|
5
|
+
attr_reader :name, :xpath, :attribute
|
6
|
+
|
7
|
+
def initialize(name, options = {})
|
8
|
+
@name = name.to_sym
|
9
|
+
@attribute = options[:attribute]
|
10
|
+
|
11
|
+
@xpath = options[:xpath]
|
12
|
+
@xpath ||= @name.to_s unless @attribute
|
13
|
+
end
|
14
|
+
|
15
|
+
def value_from(document)
|
16
|
+
node = document
|
17
|
+
|
18
|
+
begin
|
19
|
+
node = document.at(self.xpath) if self.xpath
|
20
|
+
self.attribute.nil? ? node.inner_text : node[self.attribute]
|
21
|
+
rescue NoMethodError
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|