commonthread-flickr_fu 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2008 CommonThread, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,110 @@
1
+ = flickr-fu
2
+
3
+ == Contact
4
+
5
+ Author: Ben Wyrosdick
6
+ Email: ben [at] commonthread.com
7
+ Lighthouse: http://commonthread.lighthouseapp.com/projects/12069-flickr_fu/overview
8
+ Main Repository: http://github.com/commonthread/flickr_fu/tree/master
9
+
10
+ == Getting Started
11
+
12
+ You need to first get an API key as detailed here:
13
+
14
+ http://www.flickr.com/services/api/misc.api_keys.html
15
+
16
+ == Installation
17
+
18
+ sudo gem install flickr-fu
19
+
20
+ == Documentation
21
+
22
+ RDoc Documentation can be found here:
23
+
24
+ http://www.commonthread.com/projects/flickr_fu/rdoc/
25
+
26
+ == Authorization
27
+
28
+ To authorise your application to access Flickr using your API key you will
29
+ need to access a specific URL.
30
+
31
+ To generate this URL run the following and when presented with the URL
32
+ access it from your browser. Confirm the application has permission at
33
+ the level you have specified.
34
+
35
+ Finally, cache the token (this will create the token cache file)
36
+
37
+ If you have an invalid API key you will see errors such as:
38
+
39
+ "100: Invalid API Key"
40
+
41
+ If you don't follow the process below to authorise your application
42
+ you will see errors such as:
43
+
44
+ "98: Login failed / Invalid auth token" or
45
+ "99: User not logged in / Insufficient permissions"
46
+
47
+ == Authorization Example
48
+
49
+ require 'flickr_fu'
50
+
51
+ flickr = Flickr.new('flickr.yml')
52
+
53
+ puts "visit the following url, then click <enter> once you have authorized:"
54
+
55
+ # request write permissions
56
+ puts flickr.auth.url(:write)
57
+
58
+ gets
59
+
60
+ flickr.auth.cache_token
61
+
62
+ == Search Example
63
+
64
+ require 'flickr_fu'
65
+
66
+ flickr = Flickr.new('flickr.yml')
67
+
68
+ photos = flickr.photos.search(:tags => 'ruby-flickr')
69
+
70
+ puts "found #{photos.size} photo(s)"
71
+
72
+ photos.each do |photo|
73
+ puts photo.title
74
+ puts photo.description unless [nil, ''].include?(photo.description)
75
+ [:square, :thumbnail, :small, :medium, :large, :original].each do |size|
76
+ puts "#{size}: #{photo.url(size)}"
77
+ end
78
+ puts "comments: #{photo.comments.size}"
79
+ photo.comments.each do |comment|
80
+ intro = "#{comment.author_name} says - "
81
+ puts "#{intro}\"#{comment.comment.gsub("\n", "\n"+(" "*intro.length))}\""
82
+ end
83
+ puts "notes: #{photo.notes.size}"
84
+ photo.notes.each do |note|
85
+ puts "[#{note.x},#{note.y} ~ #{note.width}x#{note.height}] - \"#{note.note}\""
86
+ end
87
+ puts
88
+ puts
89
+ end
90
+
91
+ == Another Search Example
92
+
93
+ If searching for photos by user id then you need to specify the 'alias' - without
94
+ intervention this is usually set by Flickr and is an alphanumeric string.
95
+
96
+ To find out the user id for a given user, you can use the tool at:
97
+
98
+ http://idgettr.com/
99
+
100
+ And replace the line in the above sample to query on user id:
101
+
102
+ photos = flickr.photos.search(:user_id => 'your_user_id_here')
103
+
104
+ == Patch Contributers
105
+
106
+ Chris Ledet
107
+ Maciej Biłas
108
+ Mike Perham
109
+ Chris Anderton
110
+ Luke Francl
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the contact_info plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the contact_info plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'ruby-flickr'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/flickr_fu.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "flickr_fu"
3
+ s.version = "0.1.6"
4
+ s.date = "2008-09-12"
5
+ s.summary = "Provides a ruby interface to flickr via the REST api"
6
+ s.email = "ben@commonthread.com"
7
+ s.homepage = "http://github.com/commonthread/flickr_fu"
8
+ s.description = "Provides a ruby interface to flickr via the REST api"
9
+ s.has_rdoc = true
10
+ s.authors = ["Ben Wyrosdick"]
11
+ s.files = ["README",
12
+ "LICENSE",
13
+ "Rakefile",
14
+ "flickr_fu.gemspec",
15
+ "lib/flickr/auth.rb",
16
+ "lib/flickr/base.rb",
17
+ "lib/flickr/comment.rb",
18
+ "lib/flickr/license.rb",
19
+ "lib/flickr/note.rb",
20
+ "lib/flickr/people.rb",
21
+ "lib/flickr/person.rb",
22
+ "lib/flickr/photo.rb",
23
+ "lib/flickr/photo_response.rb",
24
+ "lib/flickr/photos.rb",
25
+ "lib/flickr/size.rb",
26
+ "lib/flickr/status.rb",
27
+ "lib/flickr/test.rb",
28
+ "lib/flickr/token.rb",
29
+ "lib/flickr/uploader.rb",
30
+ "lib/flickr_fu.rb"]
31
+ s.rdoc_options = ["--main", "README"]
32
+ s.extra_rdoc_files = ["README"]
33
+ s.add_dependency("mime-types", ["> 0.0.0"])
34
+ s.add_dependency("xml-magic", ["> 0.0.0"])
35
+ end
@@ -0,0 +1,69 @@
1
+ class Flickr::Auth < Flickr::Base
2
+ def initialize(flickr)
3
+ @flickr = flickr
4
+ end
5
+
6
+ # get or return a frob to use for authentication
7
+ def frob
8
+ @frob ||= get_frob
9
+ end
10
+
11
+ # generates the authorization url to allow access to a flickr account.
12
+ #
13
+ # Params
14
+ # * perms (Optional)
15
+ # sets the permision level to grant on the flickr account.
16
+ # :read - permission to read private information (DEFAULT)
17
+ # :write - permission to add, edit and delete photo metadata (includes 'read')
18
+ # :delete - permission to delete photos (includes 'write' and 'read')
19
+ #
20
+ def url(perms = :read)
21
+ options = {:api_key => @flickr.api_key, :perms => perms, :frob => self.frob}
22
+ @flickr.sign_request(options)
23
+ Flickr::Base::AUTH_ENDPOINT + "?" + options.collect{|k,v| "#{k}=#{v}"}.join('&')
24
+ end
25
+
26
+ # gets the token object for the current frob
27
+ #
28
+ # Params
29
+ # * pass_through (Optional)
30
+ # Boolean value that determines if a call will be made to flickr to find a taken for the current frob if empty
31
+ #
32
+ def token(pass_through = true)
33
+ @token ||= get_token(pass_through) rescue nil
34
+ end
35
+
36
+ # saves the current token to the cache file if token exists
37
+ #
38
+ # Param
39
+ # * filename (Optional)
40
+ # filename of the cache file. defaults to the file passed into Flickr.new
41
+ #
42
+ def cache_token(filename = @flickr.token_cache)
43
+ if filename and self.token
44
+ cache_file = File.open(filename, 'w+')
45
+ cache_file.puts self.token.to_yaml
46
+ cache_file.close
47
+ true
48
+ else
49
+ false
50
+ end
51
+ end
52
+
53
+ private
54
+ def get_frob
55
+ rsp = @flickr.send_request('flickr.auth.getFrob')
56
+
57
+ rsp.frob.to_s
58
+ end
59
+
60
+ def get_token(pass_through)
61
+ if @flickr.token_cache and File.exists?(@flickr.token_cache)
62
+ YAML.load_file(@flickr.token_cache)
63
+ elsif pass_through
64
+ rsp = @flickr.send_request('flickr.auth.getToken', {:frob => self.frob})
65
+
66
+ Token.new(:token => rsp.auth.token.to_s, :permisions => rsp.auth.perms.to_s, :user_id => rsp.auth.user[:nsid], :username => rsp.auth.user[:username], :user_real_name => rsp.auth.user[:fullname])
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,102 @@
1
+ module Flickr
2
+ def self.new(*params)
3
+ Flickr::Base.new(*params)
4
+ end
5
+
6
+ class Base
7
+ attr_reader :api_key, :api_secret, :token_cache
8
+
9
+ REST_ENDPOINT = 'http://api.flickr.com/services/rest/'
10
+ AUTH_ENDPOINT = 'http://flickr.com/services/auth/'
11
+ UPLOAD_ENDPOINT = 'http://api.flickr.com/services/upload/'
12
+
13
+ # create a new flickr object
14
+ #
15
+ # Params
16
+ # * config_file (Required)
17
+ # yaml file to load configuration from
18
+ # * token_cache (Optional)
19
+ # location of the token cache file. This will override the setting in the config file
20
+ #
21
+ # Config Example (yaml file)
22
+ #
23
+ # ---
24
+ # key: YOUR_API_KEY
25
+ # secret: YOUR_API_SECRET
26
+ # token_cache: token.yml
27
+ #
28
+ def initialize(config_file, token_cache = nil)
29
+ config = YAML.load_file(config_file)
30
+
31
+ @api_key = config['key']
32
+ @api_secret = config['secret']
33
+ @token_cache = token_cache || config['token_cache']
34
+
35
+ raise 'flickr config file must contain an api key and secret' unless @api_key and @api_secret
36
+ end
37
+
38
+ # sends a request to the flcikr REST api
39
+ #
40
+ # Params
41
+ # * method (Required)
42
+ # name of the flickr method (ex. flickr.photos.search)
43
+ # * options (Optional)
44
+ # hash of query parameters, you do not need to include api_key, api_sig or auth_token because these are added automatically
45
+ # * http_method (Optional)
46
+ # choose between a GET and POST http request. Valid options are:
47
+ # :get (DEFAULT)
48
+ # :post
49
+ # * endpoint (Optional)
50
+ # url of the api endpoint
51
+ #
52
+ def send_request(method, options = {}, http_method = :get, endpoint = REST_ENDPOINT)
53
+ options.merge!(:api_key => @api_key, :method => method)
54
+ sign_request(options)
55
+
56
+ if http_method == :get
57
+ api_call = endpoint + "?" + options.collect{|k,v| "#{k}=#{CGI.escape(v.to_s)}"}.join('&')
58
+ rsp = Net::HTTP.get(URI.parse(api_call))
59
+ else
60
+ rsp = Net::HTTP.post_form(URI.parse(endpoint), options).body
61
+ end
62
+
63
+ rsp = '<rsp stat="ok"></rsp>' if rsp == ""
64
+ xm = XmlMagic.new(rsp)
65
+
66
+ if xm[:stat] == 'ok'
67
+ xm
68
+ else
69
+ raise "#{xm.err[:code]}: #{xm.err[:msg]}"
70
+ end
71
+ end
72
+
73
+ # alters your api parameters to include a signiture and authorization token
74
+ #
75
+ # Params
76
+ # * options (Required)
77
+ # the hash of parameters to be passed to the send_request
78
+ # * authorize (Optional)
79
+ # boolean value to determine if the call with include an auth_token (Defaults to true)
80
+ #
81
+ def sign_request(options, authorize = true)
82
+ options.merge!(:auth_token => self.auth.token(false).to_s, :api_key => @api_key) if authorize and self.auth.token(false)
83
+ options.delete(:api_sig)
84
+ options.merge!(:api_sig => Digest::MD5.hexdigest(@api_secret + options.to_a.sort_by{|k| k[0].to_s}.flatten.join)) if @api_secret
85
+ end
86
+
87
+ # creates and/or returns the Flickr::Test object
88
+ def test() @test ||= Flickr::Test.new(self) end
89
+
90
+ # creates and/or returns the Flickr::Photos object
91
+ def photos() @photos ||= Flickr::Photos.new(self) end
92
+
93
+ # creates and/or returns the Flickr::People object
94
+ def people() @people ||= Flickr::People.new(self) end
95
+
96
+ # creates and/or returns the Flickr::Auth object
97
+ def auth() @auth ||= Flickr::Auth.new(self) end
98
+
99
+ # creates and/or returns the Flickr::Uploader object
100
+ def uploader() @uploader ||= Flickr::Uploader.new(self) end
101
+ end
102
+ end
@@ -0,0 +1,16 @@
1
+ # wrapping class to hold a flickr comment
2
+ #
3
+ class Flickr::Photos::Comment
4
+ attr_accessor :id, :comment, :author, :author_name, :created_at, :permalink
5
+
6
+ # create a new instance of a flickr comment.
7
+ #
8
+ # Params
9
+ # * attributes (Required)
10
+ # a hash of attributes used to set the initial values of the comment object
11
+ def initialize(attributes)
12
+ attributes.each do |k,v|
13
+ send("#{k}=", v)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ class Flickr::Photos::License
2
+ attr_accessor :id, :name, :url
3
+
4
+ # create a new instance of a flickr photo license.
5
+ #
6
+ # Params
7
+ # * attributes (Required)
8
+ # a hash of attributes used to set the initial values of the license object
9
+ def initialize(attributes)
10
+ attributes.each do |k,v|
11
+ send("#{k}=", v)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # wrapping class to hold a flickr note
2
+ #
3
+ class Flickr::Photos::Note
4
+ attr_accessor :id, :note, :author, :author_name, :x, :y, :width, :height
5
+
6
+ # create a new instance of a flickr note.
7
+ #
8
+ # Params
9
+ # * attributes (Required)
10
+ # a hash of attributes used to set the initial values of the note object
11
+ def initialize(attributes)
12
+ attributes.each do |k,v|
13
+ send("#{k}=", v)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ class Flickr::People < Flickr::Base
2
+ def initialize(flickr)
3
+ @flickr = flickr
4
+ end
5
+
6
+ # Get information about a user.
7
+ #
8
+ # Params
9
+ # * id (Required)
10
+ # the nsid of the user to get information for
11
+ #
12
+ def find_by_id(id)
13
+ rsp = @flickr.send_request('flickr.people.getInfo', {:user_id => id})
14
+
15
+ Person.new(@flickr, :nsid => rsp.person[:nsid],
16
+ :is_admin => (rsp.person[:isadmin] == "1" ? true : false),
17
+ :is_pro => (rsp.person[:ispro] == "1" ? true : false),
18
+ :icon_server => rsp.person[:iconserver],
19
+ :icon_farm => rsp.person[:iconfarm],
20
+ :username => rsp.person.username.to_s,
21
+ :realname => rsp.person.realname.to_s,
22
+ :mbox_sha1sum => rsp.person.mbox_sha1sum.to_s,
23
+ :location => rsp.person.location.to_s,
24
+ :photos_url => rsp.person.photosurl.to_s,
25
+ :profile_url => rsp.person.profileurl.to_s,
26
+ :photo_count => rsp.person.photos.count.to_s.to_i,
27
+ :photo_first_upload => (Time.at(rsp.person.photos.firstdate.to_s.to_i) rescue nil),
28
+ :photo_first_taken => (Time.parse(rsp.person.photos.firstdatetaken.to_s) rescue nil))
29
+ end
30
+
31
+ # Get information about a user.
32
+ #
33
+ # Params
34
+ # * username (Required)
35
+ # the username of the user to get information for
36
+ #
37
+ def find_by_username(username)
38
+ rsp = @flickr.send_request('flickr.people.findByUsername', {:username => username})
39
+
40
+ find_by_id(rsp.user[:nsid])
41
+ end
42
+
43
+ # Get information about a user.
44
+ #
45
+ # Params
46
+ # * email (Required)
47
+ # the email of the user to get information for
48
+ #
49
+ def find_by_email(email)
50
+ rsp = @flickr.send_request('flickr.people.findByEmail', {:find_email => email})
51
+
52
+ find_by_id(rsp.user[:nsid])
53
+ end
54
+ end