picasa 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +6 -1
- data/Gemfile +6 -0
- data/README.md +16 -24
- data/Rakefile +1 -1
- data/lib/picasa.rb +18 -12
- data/lib/picasa/api/album.rb +45 -0
- data/lib/picasa/client.rb +14 -0
- data/lib/picasa/connection.rb +86 -0
- data/lib/picasa/exceptions.rb +17 -0
- data/lib/picasa/presenter/album.rb +76 -0
- data/lib/picasa/presenter/album_list.rb +60 -0
- data/lib/picasa/presenter/author.rb +15 -0
- data/lib/picasa/presenter/base.rb +29 -0
- data/lib/picasa/presenter/link.rb +19 -0
- data/lib/picasa/presenter/media.rb +27 -0
- data/lib/picasa/presenter/photo.rb +79 -0
- data/lib/picasa/presenter/thumbnail.rb +19 -0
- data/lib/picasa/utils.rb +44 -0
- data/lib/picasa/version.rb +1 -1
- data/picasa.gemspec +4 -15
- data/test/api/album_test.rb +24 -0
- data/test/client_test.rb +14 -0
- data/test/connection_test.rb +71 -0
- data/test/fixtures/album/album-list-with-tag.txt +105 -0
- data/test/fixtures/album/album-list.txt +105 -0
- data/test/fixtures/album/album-show-with-max-results.txt +131 -0
- data/test/fixtures/album/album-show-with-tag-and-many-photos.txt +156 -0
- data/test/fixtures/album/album-show-with-tag-and-one-photo.txt +105 -0
- data/test/fixtures/album/album-show.txt +169 -0
- data/test/fixtures/auth/failure.txt +12 -0
- data/test/fixtures/auth/success.txt +14 -0
- data/test/fixtures/json.txt +435 -0
- data/test/fixtures/photo/photo-list-all-with-q.txt +556 -0
- data/test/fixtures/photo/photo-list-all.txt +623 -0
- data/test/fixtures/photo/photo-list-user.txt +388 -0
- data/test/fixtures/presenters/album_list.xml +88 -0
- data/test/fixtures/presenters/album_show.xml +152 -0
- data/test/fixtures/presenters/album_show_with_one_photo.xml +88 -0
- data/test/fixtures/tag/tag-list-album.txt +77 -0
- data/test/fixtures/tag/tag-list-photo.txt +72 -0
- data/test/fixtures/tag/tag-list.txt +68 -0
- data/test/helper.rb +12 -6
- data/test/presenter/album_list_test.rb +67 -0
- data/test/presenter/album_test.rb +173 -0
- data/test/presenter/author_test.rb +17 -0
- data/test/presenter/base_test.rb +27 -0
- data/test/presenter/link_test.rb +21 -0
- data/test/presenter/media_test.rb +29 -0
- data/test/presenter/photo_test.rb +81 -0
- data/test/presenter/thumbnail_test.rb +24 -0
- data/test/utils_test.rb +84 -0
- metadata +66 -31
- data/lib/picasa/config.rb +0 -15
- data/lib/picasa/web_albums.rb +0 -56
- data/test/fixtures/albums +0 -15
- data/test/fixtures/photos +0 -15
- data/test/test_config.rb +0 -12
- data/test/test_web_albums.rb +0 -44
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# Picasa
|
2
2
|
|
3
|
-
|
4
|
-
Only for public albums so far.
|
3
|
+
Ruby library for [Picasa Web Albums Data API](https://developers.google.com/picasa-web/)
|
5
4
|
|
6
5
|
## Installation
|
7
6
|
|
@@ -12,34 +11,27 @@ gem install picasa
|
|
12
11
|
## Usage
|
13
12
|
|
14
13
|
``` ruby
|
15
|
-
Picasa.
|
16
|
-
|
17
|
-
#
|
18
|
-
# {another one} ]
|
19
|
-
|
20
|
-
Picasa.photos(:google_user => 'google_username', :album_id => 'album_id')
|
21
|
-
#=> {:photos => [{ :title, :thumbnail_1, :thumbnail_2, :thumbnail_3, :photo },{}],
|
22
|
-
# :slideshow => "link to picasa slideshow"}
|
23
|
-
```
|
24
|
-
|
25
|
-
or you can set google user for all requests like this:
|
14
|
+
client = Picasa::Client.new(user_id: "username@gmail.com")
|
15
|
+
client.album.list
|
16
|
+
# => Picasa::Presenter::AlbumList
|
26
17
|
|
27
|
-
|
28
|
-
|
29
|
-
c.google_user = 'google.user'
|
30
|
-
end
|
18
|
+
client.album.show("album_id")
|
19
|
+
# => Picasa::Presenter::Album
|
31
20
|
```
|
32
21
|
|
33
|
-
|
34
|
-
|
35
|
-
``` ruby
|
36
|
-
Picasa.albums
|
37
|
-
Picasa.photos(:album_id => 'album_id')
|
38
|
-
```
|
22
|
+
If password is specified, all requests will be authenticated.
|
23
|
+
This affect results to contain private data.
|
39
24
|
|
40
25
|
## Continuous Integration
|
41
26
|
[![Build Status](https://secure.travis-ci.org/morgoth/picasa.png)](http://travis-ci.org/morgoth/picasa)
|
42
27
|
|
28
|
+
## Contributors
|
29
|
+
|
30
|
+
* [Bram Wijnands](https://github.com/BRamBoo)
|
31
|
+
* [Rafael Souza](https://github.com/rafaels)
|
32
|
+
* [jsaak](https://github.com/jsaak)
|
33
|
+
* [Javier Guerra](https://github.com/javierg)
|
34
|
+
|
43
35
|
## Copyright
|
44
36
|
|
45
|
-
Copyright (c)
|
37
|
+
Copyright (c) Wojciech Wnętrzak, released under the MIT license.
|
data/Rakefile
CHANGED
data/lib/picasa.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
|
-
require "
|
2
|
-
|
1
|
+
require "multi_xml"
|
2
|
+
|
3
3
|
require "picasa/version"
|
4
|
+
require "picasa/utils"
|
5
|
+
require "picasa/exceptions"
|
6
|
+
require "picasa/connection"
|
7
|
+
require "picasa/client"
|
8
|
+
require "picasa/api/album"
|
4
9
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
+
require "picasa/presenter/album"
|
11
|
+
require "picasa/presenter/album_list"
|
12
|
+
require "picasa/presenter/author"
|
13
|
+
require "picasa/presenter/link"
|
14
|
+
require "picasa/presenter/media"
|
15
|
+
require "picasa/presenter/photo"
|
16
|
+
require "picasa/presenter/thumbnail"
|
10
17
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
18
|
+
module Picasa
|
19
|
+
API_URL = "https://picasaweb.google.com"
|
20
|
+
API_AUTH_URL = "https://www.google.com"
|
21
|
+
API_VERSION = "2"
|
16
22
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Picasa
|
2
|
+
module API
|
3
|
+
class Album
|
4
|
+
attr_reader :user_id, :credentials
|
5
|
+
|
6
|
+
# @param [Hash] credentials
|
7
|
+
# @option options [String] :user_id google username/email
|
8
|
+
# @option options [String] :password password for given username/email
|
9
|
+
def initialize(credentials)
|
10
|
+
if MultiXml.parser.to_s == "MultiXml::Parsers::Ox"
|
11
|
+
raise StandardError, "MultiXml parser is set to :ox - picasa gem will not work with it currently, use one of: :libxml, :nokogiri, :rexml"
|
12
|
+
end
|
13
|
+
@user_id = credentials.fetch(:user_id)
|
14
|
+
@credentials = credentials
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns album list
|
18
|
+
#
|
19
|
+
# @param [Hash] additional options included in request
|
20
|
+
#
|
21
|
+
# @return [Presenter::AlbumList]
|
22
|
+
def list(options = {})
|
23
|
+
uri = URI.parse("/data/feed/api/user/#{user_id}")
|
24
|
+
parsed_body = Connection.new(credentials).get(uri.path, options)
|
25
|
+
|
26
|
+
Presenter::AlbumList.new(parsed_body["feed"])
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns photo list for given album
|
30
|
+
#
|
31
|
+
# @param [String] id of album
|
32
|
+
# @param [Hash] additional options included in request
|
33
|
+
# @option options [String, Integer] :max_results max number of returned results
|
34
|
+
# @option options [String] :tag include photos with given tag only
|
35
|
+
#
|
36
|
+
# @return [Presenter::Album]
|
37
|
+
def show(album_id, options = {})
|
38
|
+
uri = URI.parse("/data/feed/api/user/#{user_id}/albumid/#{album_id}")
|
39
|
+
parsed_body = Connection.new(credentials).get(uri.path, options)
|
40
|
+
|
41
|
+
Presenter::Album.new(parsed_body["feed"])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Picasa
|
2
|
+
class Client
|
3
|
+
attr_reader :credentials
|
4
|
+
|
5
|
+
def initialize(credentials = {})
|
6
|
+
credentials[:user_id] || raise(ArgumentError, "You must specify user_id")
|
7
|
+
@credentials = credentials
|
8
|
+
end
|
9
|
+
|
10
|
+
def album
|
11
|
+
API::Album.new(credentials)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "net/https"
|
2
|
+
require "cgi"
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module Picasa
|
6
|
+
class Connection
|
7
|
+
attr_reader :user_id, :password, :response
|
8
|
+
|
9
|
+
def initialize(credentials = {})
|
10
|
+
@user_id = credentials.fetch(:user_id)
|
11
|
+
@password = credentials.fetch(:password, nil)
|
12
|
+
end
|
13
|
+
|
14
|
+
def http(url = API_URL)
|
15
|
+
uri = URI.parse(url)
|
16
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
17
|
+
http.use_ssl = true
|
18
|
+
http
|
19
|
+
end
|
20
|
+
|
21
|
+
def get(path, params = {})
|
22
|
+
authenticate if auth?
|
23
|
+
|
24
|
+
path = path_with_params(path, params)
|
25
|
+
request = Net::HTTP::Get.new(path, headers)
|
26
|
+
@response = http.request(request)
|
27
|
+
parsed_body
|
28
|
+
end
|
29
|
+
|
30
|
+
def parsed_body
|
31
|
+
@parsed_body ||= MultiXml.parse(response.body)
|
32
|
+
end
|
33
|
+
|
34
|
+
def inline_params(params)
|
35
|
+
params.map do |key, value|
|
36
|
+
dasherized = key.to_s.gsub("_", "-")
|
37
|
+
"#{CGI.escape(dasherized)}=#{CGI.escape(value.to_s)}"
|
38
|
+
end.join("&")
|
39
|
+
end
|
40
|
+
|
41
|
+
def path_with_params(path, params = {})
|
42
|
+
path = path + "?" + inline_params(params) unless params.empty?
|
43
|
+
URI.parse(path).to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def headers
|
49
|
+
{"User-Agent" => "ruby-gem-v#{Picasa::VERSION}", "GData-Version" => API_VERSION}.tap do |headers|
|
50
|
+
headers["Authorization"] = "GoogleLogin auth=#{@auth_key}" if @auth_key
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def auth?
|
55
|
+
!password.nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_email!
|
59
|
+
unless user_id =~ /[a-z0-9][a-z0-9._%+-]+[a-z0-9]@[a-z0-9][a-z0-9.-][a-z0-9]+\.[a-z]{2,6}/i
|
60
|
+
raise ArgumentError.new("user_id must be a valid E-mail address when authentication is used.")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def authenticate
|
65
|
+
return @auth_key if defined?(@auth_key)
|
66
|
+
validate_email!
|
67
|
+
|
68
|
+
data = inline_params({"accountType" => "HOSTED_OR_GOOGLE",
|
69
|
+
"Email" => user_id,
|
70
|
+
"Passwd" => password,
|
71
|
+
"service" => "lh2",
|
72
|
+
"source" => "ruby-gem-v#{Picasa::VERSION}"})
|
73
|
+
|
74
|
+
response = http(API_AUTH_URL).post("/accounts/ClientLogin", data)
|
75
|
+
raise ResponseError.new(response.body, response) unless response.is_a? Net::HTTPSuccess
|
76
|
+
|
77
|
+
@auth_key = extract_auth_key(response.body)
|
78
|
+
end
|
79
|
+
|
80
|
+
def extract_auth_key(data)
|
81
|
+
response = data.split("\n").map { |v| v.split("=") }
|
82
|
+
params = Hash[response]
|
83
|
+
params["Auth"]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Picasa
|
2
|
+
# All Picasa exceptions can be cought by rescuing:
|
3
|
+
# Picasa::StandardError
|
4
|
+
#
|
5
|
+
class StandardError < StandardError; end
|
6
|
+
|
7
|
+
class ArgumentError < StandardError; end
|
8
|
+
|
9
|
+
class ResponseError < StandardError
|
10
|
+
attr_reader :response
|
11
|
+
|
12
|
+
def initialize(message, response)
|
13
|
+
@response = response
|
14
|
+
super(message)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "picasa/presenter/base"
|
2
|
+
|
3
|
+
module Picasa
|
4
|
+
module Presenter
|
5
|
+
class Album < Base
|
6
|
+
def author
|
7
|
+
@author ||= Author.new(safe_retrieve(parsed_body, "author"))
|
8
|
+
end
|
9
|
+
|
10
|
+
def entries
|
11
|
+
@entries ||= array_wrap(safe_retrieve(parsed_body, "entry")).map { |photo| Photo.new(photo) }
|
12
|
+
end
|
13
|
+
alias :photos :entries
|
14
|
+
|
15
|
+
def links
|
16
|
+
@links ||= safe_retrieve(parsed_body, "link").map { |link| Link.new(link) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def media
|
20
|
+
@media ||= Media.new(safe_retrieve(parsed_body, "group"))
|
21
|
+
end
|
22
|
+
|
23
|
+
def published
|
24
|
+
@published ||= map_to_date(safe_retrieve(parsed_body, "published"))
|
25
|
+
end
|
26
|
+
|
27
|
+
def updated
|
28
|
+
@updated ||= map_to_date(safe_retrieve(parsed_body, "updated"))
|
29
|
+
end
|
30
|
+
|
31
|
+
def title
|
32
|
+
@title ||= safe_retrieve(parsed_body, "title")
|
33
|
+
end
|
34
|
+
|
35
|
+
def summary
|
36
|
+
@summary ||= safe_retrieve(parsed_body, "summary")
|
37
|
+
end
|
38
|
+
|
39
|
+
def rights
|
40
|
+
@rights ||= safe_retrieve(parsed_body, "rights")
|
41
|
+
end
|
42
|
+
|
43
|
+
def id
|
44
|
+
@id ||= array_wrap(safe_retrieve(parsed_body, "id"))[1]
|
45
|
+
end
|
46
|
+
|
47
|
+
def name
|
48
|
+
@name ||= safe_retrieve(parsed_body, "name")
|
49
|
+
end
|
50
|
+
|
51
|
+
def location
|
52
|
+
@location ||= safe_retrieve(parsed_body, "location")
|
53
|
+
end
|
54
|
+
|
55
|
+
def access
|
56
|
+
@access ||= safe_retrieve(parsed_body, "access")
|
57
|
+
end
|
58
|
+
|
59
|
+
def timestamp
|
60
|
+
@timestamp ||= safe_retrieve(parsed_body, "timestamp")
|
61
|
+
end
|
62
|
+
|
63
|
+
def numphotos
|
64
|
+
@numphotos ||= map_to_integer(safe_retrieve(parsed_body, "numphotos"))
|
65
|
+
end
|
66
|
+
|
67
|
+
def user
|
68
|
+
@user ||= safe_retrieve(parsed_body, "user")
|
69
|
+
end
|
70
|
+
|
71
|
+
def nickname
|
72
|
+
@nickname ||= safe_retrieve(parsed_body, "nickname")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "picasa/presenter/base"
|
2
|
+
|
3
|
+
module Picasa
|
4
|
+
module Presenter
|
5
|
+
class AlbumList < Base
|
6
|
+
def author
|
7
|
+
@author ||= Author.new(safe_retrieve(parsed_body, "author"))
|
8
|
+
end
|
9
|
+
|
10
|
+
def entries
|
11
|
+
@entries ||= array_wrap(safe_retrieve(parsed_body, "entry")).map { |entry| Album.new(entry) }
|
12
|
+
end
|
13
|
+
alias :albums :entries
|
14
|
+
|
15
|
+
def links
|
16
|
+
@links ||= safe_retrieve(parsed_body, "link").map { |link| Link.new(link) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def title
|
20
|
+
@title ||= safe_retrieve(parsed_body, "title")
|
21
|
+
end
|
22
|
+
|
23
|
+
def updated
|
24
|
+
@updated ||= map_to_date(safe_retrieve(parsed_body, "updated"))
|
25
|
+
end
|
26
|
+
|
27
|
+
def icon
|
28
|
+
@icon ||= safe_retrieve(parsed_body, "icon")
|
29
|
+
end
|
30
|
+
|
31
|
+
def generator
|
32
|
+
@generator ||= safe_retrieve(parsed_body, "generator", "__content__")
|
33
|
+
end
|
34
|
+
|
35
|
+
def total_results
|
36
|
+
@total_results ||= map_to_integer(safe_retrieve(parsed_body, "totalResults"))
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_index
|
40
|
+
@start_index ||= map_to_integer(safe_retrieve(parsed_body, "startIndex"))
|
41
|
+
end
|
42
|
+
|
43
|
+
def items_per_page
|
44
|
+
@items_per_page ||= map_to_integer(safe_retrieve(parsed_body, "itemsPerPage"))
|
45
|
+
end
|
46
|
+
|
47
|
+
def user
|
48
|
+
@user ||= safe_retrieve(parsed_body, "user")
|
49
|
+
end
|
50
|
+
|
51
|
+
def nickname
|
52
|
+
@nickname ||= safe_retrieve(parsed_body, "nickname")
|
53
|
+
end
|
54
|
+
|
55
|
+
def thumbnail
|
56
|
+
@thumbnail ||= safe_retrieve(parsed_body, "thumbnail")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|