fleakr 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +114 -19
- data/Rakefile +1 -1
- data/lib/fleakr/api/file_parameter.rb +47 -0
- data/lib/fleakr/api/method_request.rb +57 -0
- data/lib/fleakr/api/parameter.rb +35 -0
- data/lib/fleakr/api/parameter_list.rb +96 -0
- data/lib/fleakr/api/response.rb +2 -2
- data/lib/fleakr/api/upload_request.rb +64 -0
- data/lib/fleakr/api/value_parameter.rb +36 -0
- data/lib/fleakr/api.rb +7 -0
- data/lib/fleakr/core_ext/hash.rb +22 -0
- data/lib/fleakr/core_ext.rb +1 -0
- data/lib/fleakr/objects/authentication_token.rb +43 -0
- data/lib/fleakr/objects/contact.rb +5 -5
- data/lib/fleakr/objects/error.rb +2 -2
- data/lib/fleakr/objects/group.rb +2 -2
- data/lib/fleakr/objects/image.rb +7 -7
- data/lib/fleakr/objects/photo.rb +69 -5
- data/lib/fleakr/objects/search.rb +3 -6
- data/lib/fleakr/objects/set.rb +11 -5
- data/lib/fleakr/objects/user.rb +14 -26
- data/lib/fleakr/objects.rb +9 -0
- data/lib/fleakr/support/attribute.rb +30 -12
- data/lib/fleakr/support/object.rb +20 -4
- data/lib/fleakr/support.rb +2 -0
- data/lib/fleakr/version.rb +1 -1
- data/lib/fleakr.rb +66 -7
- data/test/fixtures/auth.checkToken.xml +8 -0
- data/test/fixtures/auth.getFullToken.xml +8 -0
- data/test/fixtures/people.getInfo.xml +1 -1
- data/test/fixtures/photos.getInfo.xml +20 -0
- data/test/test_helper.rb +18 -3
- data/test/unit/fleakr/api/file_parameter_test.rb +63 -0
- data/test/unit/fleakr/api/method_request_test.rb +103 -0
- data/test/unit/fleakr/api/parameter_list_test.rb +161 -0
- data/test/unit/fleakr/api/parameter_test.rb +34 -0
- data/test/unit/fleakr/api/upload_request_test.rb +133 -0
- data/test/unit/fleakr/api/value_parameter_test.rb +41 -0
- data/test/unit/fleakr/core_ext/hash_test.rb +32 -0
- data/test/unit/fleakr/objects/authentication_token_test.rb +47 -0
- data/test/unit/fleakr/objects/image_test.rb +10 -5
- data/test/unit/fleakr/objects/photo_test.rb +96 -36
- data/test/unit/fleakr/objects/search_test.rb +1 -1
- data/test/unit/fleakr/objects/set_test.rb +12 -1
- data/test/unit/fleakr/objects/user_test.rb +2 -16
- data/test/unit/fleakr/support/attribute_test.rb +82 -24
- data/test/unit/fleakr/support/object_test.rb +26 -3
- data/test/unit/fleakr_test.rb +65 -6
- metadata +28 -5
- data/lib/fleakr/api/request.rb +0 -58
- data/test/unit/fleakr/api/request_test.rb +0 -93
data/lib/fleakr/objects/image.rb
CHANGED
@@ -24,11 +24,11 @@ module Fleakr
|
|
24
24
|
|
25
25
|
include Fleakr::Support::Object
|
26
26
|
|
27
|
-
flickr_attribute :size, :
|
28
|
-
flickr_attribute :width
|
29
|
-
flickr_attribute :height
|
30
|
-
flickr_attribute :url, :
|
31
|
-
flickr_attribute :page, :
|
27
|
+
flickr_attribute :size, :from => '@label'
|
28
|
+
flickr_attribute :width
|
29
|
+
flickr_attribute :height
|
30
|
+
flickr_attribute :url, :from => '@source'
|
31
|
+
flickr_attribute :page, :from => '@url'
|
32
32
|
|
33
33
|
find_all :by_photo_id, :call => 'photos.getSizes', :path => 'sizes/size'
|
34
34
|
|
@@ -41,8 +41,8 @@ module Fleakr
|
|
41
41
|
# directory, the file will be created with the original filename from Flickr.
|
42
42
|
# If the target is a file, it will be saved with the specified name. In the
|
43
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}"
|
44
|
+
def save_to(target, prefix = nil)
|
45
|
+
destination = File.directory?(target) ? "#{target}/#{prefix}#{self.filename}" : "#{target}"
|
46
46
|
File.open(destination, 'w') {|f| f << Net::HTTP.get(URI.parse(self.url)) }
|
47
47
|
end
|
48
48
|
|
data/lib/fleakr/objects/photo.rb
CHANGED
@@ -7,6 +7,10 @@ module Fleakr
|
|
7
7
|
#
|
8
8
|
# [id] The ID for this photo
|
9
9
|
# [title] The title of this photo
|
10
|
+
# [description] The description of this photo
|
11
|
+
# [secret] This photo's secret (used for sharing photo without permissions checking)
|
12
|
+
# [comment_count] Count of the comments attached to this photo
|
13
|
+
# [url] This photo's page on Flickr
|
10
14
|
# [square] The tiny square representation of this photo
|
11
15
|
# [thumbnail] The thumbnail for this photo
|
12
16
|
# [small] The small representation of this photo
|
@@ -25,18 +29,78 @@ module Fleakr
|
|
25
29
|
|
26
30
|
include Fleakr::Support::Object
|
27
31
|
|
28
|
-
flickr_attribute :
|
29
|
-
flickr_attribute :
|
30
|
-
flickr_attribute :
|
31
|
-
flickr_attribute :
|
32
|
-
flickr_attribute :
|
32
|
+
flickr_attribute :id, :from => ['@id', 'photoid']
|
33
|
+
flickr_attribute :title
|
34
|
+
flickr_attribute :description
|
35
|
+
flickr_attribute :farm_id, :from => '@farm'
|
36
|
+
flickr_attribute :server_id, :from => '@server'
|
37
|
+
flickr_attribute :secret
|
38
|
+
flickr_attribute :posted
|
39
|
+
flickr_attribute :taken
|
40
|
+
flickr_attribute :updated, :from => '@lastupdate'
|
41
|
+
flickr_attribute :comment_count, :from => 'comments'
|
42
|
+
flickr_attribute :url
|
43
|
+
|
44
|
+
# TODO:
|
45
|
+
# * owner (user)
|
46
|
+
# * visibility
|
47
|
+
# * editability
|
48
|
+
# * usage
|
49
|
+
# * notes
|
50
|
+
# * tags
|
33
51
|
|
34
52
|
find_all :by_photoset_id, :call => 'photosets.getPhotos', :path => 'photoset/photo'
|
35
53
|
find_all :by_user_id, :call => 'people.getPublicPhotos', :path => 'photos/photo'
|
36
54
|
find_all :by_group_id, :call => 'groups.pools.getPhotos', :path => 'photos/photo'
|
37
55
|
|
56
|
+
find_one :by_id, :using => :photo_id, :call => 'photos.getInfo', :authenticate? => true
|
57
|
+
|
58
|
+
lazily_load :posted, :taken, :updated, :comment_count, :url, :description, :with => :load_info
|
59
|
+
|
38
60
|
has_many :images
|
39
61
|
|
62
|
+
# Upload the photo specified by <tt>filename</tt> to the user's Flickr account. This
|
63
|
+
# call requires authentication.
|
64
|
+
#
|
65
|
+
def self.upload(filename)
|
66
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename)
|
67
|
+
photo = Photo.new(response.body)
|
68
|
+
Photo.find_by_id(photo.id, :authenticate? => true)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Replace the current photo's image with the one specified by filename. This
|
72
|
+
# call requires authentication.
|
73
|
+
#
|
74
|
+
def replace_with(filename)
|
75
|
+
response = Fleakr::Api::UploadRequest.with_response!(filename, :photo_id => self.id, :type => :update)
|
76
|
+
self.populate_from(response.body)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: Refactor this to remove duplication w/ User#load_info - possibly in the lazily_load class method
|
81
|
+
def load_info # :nodoc:
|
82
|
+
response = Fleakr::Api::MethodRequest.with_response!('photos.getInfo', :photo_id => self.id)
|
83
|
+
self.populate_from(response.body)
|
84
|
+
end
|
85
|
+
|
86
|
+
# When was this photo posted?
|
87
|
+
#
|
88
|
+
def posted_at
|
89
|
+
Time.at(posted.to_i)
|
90
|
+
end
|
91
|
+
|
92
|
+
# When was this photo taken?
|
93
|
+
#
|
94
|
+
def taken_at
|
95
|
+
Time.parse(taken)
|
96
|
+
end
|
97
|
+
|
98
|
+
# When was this photo last updated? This includes addition of tags and other metadata.
|
99
|
+
#
|
100
|
+
def updated_at
|
101
|
+
Time.at(updated.to_i)
|
102
|
+
end
|
103
|
+
|
40
104
|
# Create methods to access image sizes by name
|
41
105
|
SIZES.each do |size|
|
42
106
|
define_method(size) do
|
@@ -9,13 +9,10 @@ module Fleakr
|
|
9
9
|
|
10
10
|
# Retrieve search results from the API
|
11
11
|
def results
|
12
|
-
|
13
|
-
response = Fleakr::Api::
|
14
|
-
|
15
|
-
Photo.new(flickr_photo)
|
16
|
-
end
|
12
|
+
@results ||= begin
|
13
|
+
response = Fleakr::Api::MethodRequest.with_response!('photos.search', parameters)
|
14
|
+
(response.body/'rsp/photos/photo').map {|p| Photo.new(p) }
|
17
15
|
end
|
18
|
-
@results
|
19
16
|
end
|
20
17
|
|
21
18
|
private
|
data/lib/fleakr/objects/set.rb
CHANGED
@@ -8,6 +8,7 @@ module Fleakr
|
|
8
8
|
# [id] The ID for this photoset
|
9
9
|
# [title] The title of this photoset
|
10
10
|
# [description] The description of this set
|
11
|
+
# [count] Count of photos in this set
|
11
12
|
#
|
12
13
|
# == Associations
|
13
14
|
#
|
@@ -19,26 +20,31 @@ module Fleakr
|
|
19
20
|
|
20
21
|
has_many :photos, :using => :photoset_id
|
21
22
|
|
22
|
-
flickr_attribute :id
|
23
|
+
flickr_attribute :id
|
23
24
|
flickr_attribute :title
|
24
25
|
flickr_attribute :description
|
26
|
+
flickr_attribute :count, :from => '@photos'
|
25
27
|
|
26
28
|
find_all :by_user_id, :call => 'photosets.getList', :path => 'photosets/photoset'
|
27
29
|
|
28
|
-
# Save all photos in this set to the specified directory
|
30
|
+
# Save all photos in this set to the specified directory for the specified size. Allowed
|
29
31
|
# 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
|
32
|
+
# <tt>:large</tt>, and <tt>:original</tt>. When saving the set, this method will create
|
31
33
|
# a subdirectory based on the set's title.
|
32
34
|
#
|
33
35
|
def save_to(path, size)
|
34
36
|
target = "#{path}/#{self.title}"
|
35
37
|
FileUtils.mkdir(target) unless File.exist?(target)
|
36
38
|
|
37
|
-
self.photos.
|
39
|
+
self.photos.each_with_index do |photo, index|
|
38
40
|
image = photo.send(size)
|
39
|
-
image.save_to(target) unless image.nil?
|
41
|
+
image.save_to(target, file_prefix(index)) unless image.nil?
|
40
42
|
end
|
41
43
|
end
|
44
|
+
|
45
|
+
def file_prefix(index) # :nodoc:
|
46
|
+
sprintf("%0#{self.count.length}d_", (index + 1))
|
47
|
+
end
|
42
48
|
|
43
49
|
end
|
44
50
|
end
|
data/lib/fleakr/objects/user.rb
CHANGED
@@ -11,6 +11,7 @@ module Fleakr
|
|
11
11
|
# [id] The ID for this user (also referred to as the NSID in the API docs)
|
12
12
|
# [username] This user's username
|
13
13
|
# [name] This user's full name (if entered)
|
14
|
+
# [location] This user's location (if entered)
|
14
15
|
# [photos_url] The direct URL to this user's photostream
|
15
16
|
# [profile_url] The direct URL to this user's profile
|
16
17
|
# [photos_count] The number of photos that this user has uploaded
|
@@ -42,37 +43,24 @@ module Fleakr
|
|
42
43
|
|
43
44
|
include Fleakr::Support::Object
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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'
|
46
|
+
flickr_attribute :id, :from => 'user@nsid'
|
47
|
+
flickr_attribute :username
|
48
|
+
flickr_attribute :name, :from => 'person/realname'
|
49
|
+
flickr_attribute :location
|
50
|
+
flickr_attribute :photos_url, :from => 'person/photosurl'
|
51
|
+
flickr_attribute :profile_url, :from => 'person/profileurl'
|
52
|
+
flickr_attribute :photos_count, :from => 'person/photos/count'
|
53
|
+
flickr_attribute :icon_server, :from => 'person@iconserver'
|
54
|
+
flickr_attribute :icon_farm, :from => 'person@iconfarm'
|
55
|
+
flickr_attribute :pro, :from => 'person@ispro'
|
56
|
+
flickr_attribute :admin, :from => 'person@isadmin'
|
69
57
|
|
70
58
|
has_many :sets, :groups, :photos, :contacts
|
71
59
|
|
72
60
|
find_one :by_username, :call => 'people.findByUsername'
|
73
61
|
find_one :by_email, :using => :find_email, :call => 'people.findByEmail'
|
74
62
|
|
75
|
-
lazily_load :name, :photos_url, :profile_url, :photos_count, :with => :load_info
|
63
|
+
lazily_load :name, :photos_url, :profile_url, :photos_count, :location, :with => :load_info
|
76
64
|
lazily_load :icon_server, :icon_farm, :pro, :admin, :with => :load_info
|
77
65
|
|
78
66
|
scoped_search
|
@@ -97,7 +85,7 @@ module Fleakr
|
|
97
85
|
end
|
98
86
|
|
99
87
|
def load_info # :nodoc:
|
100
|
-
response = Fleakr::Api::
|
88
|
+
response = Fleakr::Api::MethodRequest.with_response!('people.getInfo', :user_id => self.id)
|
101
89
|
self.populate_from(response.body)
|
102
90
|
end
|
103
91
|
|
@@ -0,0 +1,9 @@
|
|
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'
|
7
|
+
require 'fleakr/objects/search'
|
8
|
+
require 'fleakr/objects/set'
|
9
|
+
require 'fleakr/objects/user'
|
@@ -2,25 +2,43 @@ module Fleakr
|
|
2
2
|
module Support # :nodoc:all
|
3
3
|
class Attribute
|
4
4
|
|
5
|
-
|
5
|
+
# TODO: Refactor the location / attribute logic into a Source class
|
6
6
|
|
7
|
-
|
7
|
+
attr_reader :name, :sources
|
8
|
+
|
9
|
+
def initialize(name, sources = nil)
|
8
10
|
@name = name.to_sym
|
9
|
-
|
11
|
+
|
12
|
+
@sources = Array(sources)
|
13
|
+
@sources << @name.to_s if @sources.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def split(source)
|
17
|
+
location, attribute = source.split('@')
|
18
|
+
location = self.name.to_s if location.blank?
|
19
|
+
|
20
|
+
[location, attribute]
|
21
|
+
end
|
22
|
+
|
23
|
+
def node_for(document, source)
|
24
|
+
document.at(location(source)) || document.search("//[@#{attribute(source)}]").first
|
25
|
+
end
|
10
26
|
|
11
|
-
|
12
|
-
|
27
|
+
def attribute(source)
|
28
|
+
location, attribute = source.split('@')
|
29
|
+
attribute || location
|
30
|
+
end
|
31
|
+
|
32
|
+
def location(source)
|
33
|
+
split(source).first
|
13
34
|
end
|
14
35
|
|
15
36
|
def value_from(document)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
node = document.at(self.xpath) if self.xpath
|
20
|
-
self.attribute.nil? ? node.inner_text : node[self.attribute]
|
21
|
-
rescue NoMethodError
|
22
|
-
nil
|
37
|
+
values = sources.map do |source|
|
38
|
+
node = node_for(document, source)
|
39
|
+
(node.attributes[attribute(source)] || node.inner_text) unless node.nil?
|
23
40
|
end
|
41
|
+
values.compact.first
|
24
42
|
end
|
25
43
|
|
26
44
|
end
|
@@ -9,7 +9,7 @@ module Fleakr
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def flickr_attribute(name, options = {})
|
12
|
-
self.attributes << Attribute.new(name, options)
|
12
|
+
self.attributes << Attribute.new(name, options[:from])
|
13
13
|
class_eval "attr_accessor :#{name}"
|
14
14
|
end
|
15
15
|
|
@@ -34,7 +34,7 @@ module Fleakr
|
|
34
34
|
|
35
35
|
class_eval <<-CODE
|
36
36
|
def self.find_all_#{condition}(value)
|
37
|
-
response = Fleakr::Api::
|
37
|
+
response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', :#{attribute} => value)
|
38
38
|
(response.body/'rsp/#{options[:path]}').map {|e| #{target_class}.new(e) }
|
39
39
|
end
|
40
40
|
CODE
|
@@ -44,8 +44,10 @@ module Fleakr
|
|
44
44
|
attribute = options[:using].nil? ? condition.to_s.sub(/^by_/, '') : options[:using]
|
45
45
|
|
46
46
|
class_eval <<-CODE
|
47
|
-
def self.find_#{condition}(value)
|
48
|
-
|
47
|
+
def self.find_#{condition}(value, options = {})
|
48
|
+
options.merge!(:#{attribute} => value)
|
49
|
+
|
50
|
+
response = Fleakr::Api::MethodRequest.with_response!('#{options[:call]}', options)
|
49
51
|
#{self.name}.new(response.body)
|
50
52
|
end
|
51
53
|
CODE
|
@@ -60,6 +62,20 @@ module Fleakr
|
|
60
62
|
end
|
61
63
|
CODE
|
62
64
|
end
|
65
|
+
|
66
|
+
def lazily_load(*attributes)
|
67
|
+
options = attributes.extract_options!
|
68
|
+
|
69
|
+
attributes.each do |attribute|
|
70
|
+
class_eval <<-CODE
|
71
|
+
def #{attribute}_with_loading
|
72
|
+
self.send(:#{options[:with]}) if @#{attribute}.nil?
|
73
|
+
#{attribute}_without_loading
|
74
|
+
end
|
75
|
+
alias_method_chain :#{attribute}, :loading
|
76
|
+
CODE
|
77
|
+
end
|
78
|
+
end
|
63
79
|
|
64
80
|
end
|
65
81
|
|
data/lib/fleakr/version.rb
CHANGED
data/lib/fleakr.rb
CHANGED
@@ -6,13 +6,16 @@ require 'net/http'
|
|
6
6
|
require 'rubygems'
|
7
7
|
require 'hpricot'
|
8
8
|
require 'activesupport'
|
9
|
+
require 'md5'
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
require 'fleakr/api'
|
12
|
+
require 'fleakr/core_ext'
|
13
|
+
require 'fleakr/support'
|
14
|
+
require 'fleakr/objects'
|
14
15
|
|
15
|
-
# = Fleakr: A
|
16
|
+
# = Fleakr: A small, yet powerful, gem to interface with Flickr photostreams
|
17
|
+
#
|
18
|
+
# == Quick Start
|
16
19
|
#
|
17
20
|
# Getting started is easy, just make sure you have a valid API key from Flickr and you can
|
18
21
|
# then start making any non-authenticated request to pull back data for yours and others'
|
@@ -36,10 +39,42 @@ end
|
|
36
39
|
# user.groups
|
37
40
|
#
|
38
41
|
# To see what other associations and attributes are available, see the Fleakr::Objects::User class
|
42
|
+
#
|
43
|
+
# == Authentication
|
44
|
+
#
|
45
|
+
# If you want to do something more than just retrieve public photos (like upload your own),
|
46
|
+
# you'll need to generate an authentication token to use across requests and sessions.
|
47
|
+
#
|
48
|
+
# Assuming you've already applied for a key, go back and make sure you have the right settings
|
49
|
+
# to get your auth token. Click on the 'Edit key details' link and ensure that:
|
50
|
+
#
|
51
|
+
# 1. Your application description and notes are up-to-date
|
52
|
+
# 1. The value for 'Authentication Type' is set to 'Mobile Application'
|
53
|
+
# 1. The value for 'Mobile Permissions' is set to either 'write' or 'delete'
|
54
|
+
#
|
55
|
+
# Once this is set, you'll see your Authentication URL on the key details page (it will look
|
56
|
+
# something like http://www.flickr.com/auth-534525246245). Paste this URL into your browser and
|
57
|
+
# confirm access to get your mini-token. Now you're ready to make authenticated requests:
|
58
|
+
#
|
59
|
+
# require 'rubygems'
|
60
|
+
# require 'fleakr'
|
61
|
+
#
|
62
|
+
# Fleakr.api_key = 'ABC123'
|
63
|
+
# Fleakr.shared_secret = 'sekrit' # Available with your key details on the Flickr site
|
64
|
+
# Fleakr.mini_token = '362-133-214'
|
65
|
+
#
|
66
|
+
# Fleakr.upload('/path/to/my/photo.jpg')
|
67
|
+
# Fleakr.token.value # => "34132412341235-12341234ef34"
|
68
|
+
#
|
69
|
+
# Once you use the mini-token once, it is no longer available. To use the generated auth_token
|
70
|
+
# for future requests, just set Fleakr.auth_token to the generated value.
|
39
71
|
#
|
40
72
|
module Fleakr
|
41
73
|
|
42
|
-
|
74
|
+
# Generic catch-all exception for any API errors
|
75
|
+
class ApiError < StandardError; end
|
76
|
+
|
77
|
+
mattr_accessor :api_key, :shared_secret, :mini_token, :auth_token
|
43
78
|
|
44
79
|
# Find a user based on some unique user data. This method will try to find
|
45
80
|
# the user based on username and will fall back to email if that fails. Example:
|
@@ -51,7 +86,7 @@ module Fleakr
|
|
51
86
|
def self.user(user_data)
|
52
87
|
begin
|
53
88
|
Objects::User.find_by_username(user_data)
|
54
|
-
rescue
|
89
|
+
rescue ApiError
|
55
90
|
Objects::User.find_by_email(user_data)
|
56
91
|
end
|
57
92
|
end
|
@@ -71,4 +106,28 @@ module Fleakr
|
|
71
106
|
Objects::Search.new(params).results
|
72
107
|
end
|
73
108
|
|
109
|
+
# Upload one or more files to your Flickr account (requires authentication). Simply provide
|
110
|
+
# a filename or a pattern to upload one or more files:
|
111
|
+
#
|
112
|
+
# Fleakr.upload('/path/to/my/mug.jpg')
|
113
|
+
# Fleakr.upload('/User/Pictures/Party/*.jpg')
|
114
|
+
#
|
115
|
+
def self.upload(glob)
|
116
|
+
Dir[glob].each {|file| Fleakr::Objects::Photo.upload(file) }
|
117
|
+
end
|
118
|
+
|
119
|
+
# Get the authentication token needed for authenticated requests. Will either use
|
120
|
+
# a valid auth_token (if available) or a mini-token to generate the auth_token.
|
121
|
+
#
|
122
|
+
def self.token
|
123
|
+
@token ||= begin
|
124
|
+
if !Fleakr.auth_token.nil?
|
125
|
+
Fleakr::Objects::AuthenticationToken.from_auth_token(Fleakr.auth_token)
|
126
|
+
else
|
127
|
+
Fleakr::Objects::AuthenticationToken.from_mini_token(Fleakr.mini_token)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
74
133
|
end
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<username>frootpantz</username>
|
5
5
|
<realname>Sir Froot Pantz</realname>
|
6
6
|
<mbox_sha1sum>e52ed1e5b91c763694995460e9796fc2adc02019</mbox_sha1sum>
|
7
|
-
<location
|
7
|
+
<location>The Moon</location>
|
8
8
|
<photosurl>http://www.flickr.com/photos/frootpantz/</photosurl>
|
9
9
|
<profileurl>http://www.flickr.com/people/frootpantz/</profileurl>
|
10
10
|
<mobileurl>http://m.flickr.com/photostream.gne?id=34225</mobileurl>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8" ?>
|
2
|
+
<rsp stat="ok">
|
3
|
+
<photo id="1" secret="secret" server="3085" farm="4" dateuploaded="1230274722" isfavorite="0" license="0" rotation="0" originalsecret="sekrit" originalformat="jpg" media="photo">
|
4
|
+
<owner nsid="31066442@N69" username="frootpantz" realname="" location="" />
|
5
|
+
<title>Tree</title>
|
6
|
+
<description>A Tree</description>
|
7
|
+
<visibility ispublic="1" isfriend="0" isfamily="0" />
|
8
|
+
<dates posted="1230274722" taken="2008-12-25 18:26:55" takengranularity="0" lastupdate="1230276652" />
|
9
|
+
|
10
|
+
<editability cancomment="0" canaddmeta="0" />
|
11
|
+
<usage candownload="1" canblog="0" canprint="0" />
|
12
|
+
<comments>0</comments>
|
13
|
+
<notes />
|
14
|
+
<tags />
|
15
|
+
<urls>
|
16
|
+
<url type="photopage">http://www.flickr.com/photos/yes/1</url>
|
17
|
+
</urls>
|
18
|
+
|
19
|
+
</photo>
|
20
|
+
</rsp>
|
data/test/test_helper.rb
CHANGED
@@ -9,6 +9,19 @@ require File.dirname(__FILE__) + '/../lib/fleakr'
|
|
9
9
|
|
10
10
|
class Test::Unit::TestCase
|
11
11
|
|
12
|
+
def self.should_autoload_when_accessing(*attributes)
|
13
|
+
options = attributes.extract_options!
|
14
|
+
attributes.each do |accessor_name|
|
15
|
+
it "should load the additional user information when accessing the :#{accessor_name} attribute" do
|
16
|
+
klass = self.class.name.sub(/Test$/, '').constantize
|
17
|
+
|
18
|
+
object = klass.new
|
19
|
+
object.expects(options[:with]).with()
|
20
|
+
object.send(accessor_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
12
25
|
def self.should_have_a_value_for(attribute_test)
|
13
26
|
it "should have a value for :#{attribute_test.keys.first}" do
|
14
27
|
@object.send(attribute_test.keys.first).should == attribute_test.values.first
|
@@ -64,12 +77,14 @@ class Test::Unit::TestCase
|
|
64
77
|
klass = "Fleakr::Objects::#{class_name}".constantize
|
65
78
|
object_type = class_name.downcase
|
66
79
|
|
80
|
+
condition_value = '1'
|
81
|
+
|
67
82
|
options[:with] = options[:by] if options[:with].nil?
|
83
|
+
params = {options[:with] => condition_value}
|
68
84
|
|
69
85
|
it "should be able to find a #{thing} by #{options[:by]}" do
|
70
|
-
condition_value = '1'
|
71
86
|
stub = stub()
|
72
|
-
response = mock_request_cycle :for => options[:call], :with =>
|
87
|
+
response = mock_request_cycle :for => options[:call], :with => params
|
73
88
|
|
74
89
|
klass.expects(:new).with(response.body).returns(stub)
|
75
90
|
klass.send("find_by_#{options[:by]}".to_sym, condition_value).should == stub
|
@@ -108,7 +123,7 @@ class Test::Unit::TestCase
|
|
108
123
|
|
109
124
|
def mock_request_cycle(options)
|
110
125
|
response = stub(:body => Hpricot.XML(read_fixture(options[:for])))
|
111
|
-
Fleakr::Api::
|
126
|
+
Fleakr::Api::MethodRequest.expects(:with_response!).with(options[:for], options[:with]).returns(response)
|
112
127
|
|
113
128
|
response
|
114
129
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../../test_helper'
|
2
|
+
|
3
|
+
module Fleakr::Api
|
4
|
+
class FileParameterTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
describe "An instance of the FileParameter class" do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@temp_dir = File.expand_path(create_temp_directory)
|
10
|
+
@filename = "#{@temp_dir}/image.jpg"
|
11
|
+
end
|
12
|
+
|
13
|
+
after do
|
14
|
+
FileUtils.rm_rf(@temp_dir)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should know not to include itself in the parameter signature" do
|
18
|
+
parameter = FileParameter.new('photo', @filename)
|
19
|
+
parameter.include_in_signature?.should be(false)
|
20
|
+
end
|
21
|
+
|
22
|
+
{'jpg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif'}.each do |ext, mime_type|
|
23
|
+
it "should know the correct MIME type for an extension of #{ext}" do
|
24
|
+
parameter = FileParameter.new('photo', "#{@temp_dir}/image.#{ext}")
|
25
|
+
parameter.mime_type.should == mime_type
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should retrieve the contents of the file when accessing the value" do
|
30
|
+
File.expects(:read).with(@filename).returns('bopbip')
|
31
|
+
|
32
|
+
parameter = FileParameter.new('photo', @filename)
|
33
|
+
parameter.value.should == 'bopbip'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should cache the file contents after retrieving them" do
|
37
|
+
File.expects(:read).with(@filename).once.returns('bopbip')
|
38
|
+
|
39
|
+
parameter = FileParameter.new('photo', @filename)
|
40
|
+
2.times { parameter.value }
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should know how to generate a form representation of itself" do
|
44
|
+
filename = 'image.jpg'
|
45
|
+
mime_type = 'image/jpeg'
|
46
|
+
|
47
|
+
parameter = FileParameter.new('photo', filename)
|
48
|
+
parameter.stubs(:mime_type).with().returns(mime_type)
|
49
|
+
parameter.stubs(:value).with().returns('data')
|
50
|
+
|
51
|
+
expected =
|
52
|
+
"Content-Disposition: form-data; name=\"photo\"; filename=\"#{filename}\"\r\n" +
|
53
|
+
"Content-Type: image/jpeg\r\n" +
|
54
|
+
"\r\n" +
|
55
|
+
"data\r\n"
|
56
|
+
|
57
|
+
parameter.to_form.should == expected
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|