picasa 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +4 -0
- data/README.md +25 -2
- data/extra/Thorfile +41 -0
- data/lib/picasa.rb +4 -0
- data/lib/picasa/api/album.rb +45 -14
- data/lib/picasa/api/base.rb +18 -0
- data/lib/picasa/api/photo.rb +30 -0
- data/lib/picasa/api/tag.rb +5 -16
- data/lib/picasa/client.rb +11 -0
- data/lib/picasa/connection.rb +34 -14
- data/lib/picasa/exceptions.rb +2 -0
- data/lib/picasa/file.rb +36 -0
- data/lib/picasa/presenter/album.rb +16 -1
- data/lib/picasa/presenter/album_list.rb +1 -1
- data/lib/picasa/presenter/photo.rb +5 -0
- data/lib/picasa/presenter/tag.rb +6 -1
- data/lib/picasa/presenter/tag_list.rb +1 -1
- data/lib/picasa/template.rb +25 -0
- data/lib/picasa/templates/new_album.xml.erb +19 -0
- data/lib/picasa/templates/new_photo.xml.erb +15 -0
- data/lib/picasa/utils.rb +1 -1
- data/lib/picasa/version.rb +1 -1
- data/test/api/album_test.rb +22 -0
- data/test/api/photo_test.rb +46 -0
- data/test/connection_test.rb +15 -11
- data/test/file_test.rb +29 -0
- data/test/fixtures/album/album-create.txt +21 -0
- data/test/fixtures/{auth/failure.txt → exceptions/forbidden.txt} +0 -0
- data/test/fixtures/{not_found.txt → exceptions/not_found.txt} +0 -0
- data/test/fixtures/exceptions/precondition_failed.txt +14 -0
- data/test/fixtures/lena.jpg +0 -0
- data/test/fixtures/photo/photo-created.txt +21 -0
- data/test/helper.rb +4 -0
- data/test/presenter/album_test.rb +16 -0
- data/test/presenter/photo_test.rb +4 -0
- data/test/presenter/tag_test.rb +4 -0
- data/test/template_test.rb +25 -0
- metadata +18 -4
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -19,17 +19,40 @@ client.album.list
|
|
19
19
|
|
20
20
|
client.album.show("album_id")
|
21
21
|
# => Picasa::Presenter::Album
|
22
|
+
|
23
|
+
client.photo.create("album_id", file_path: "path/to/my-photo.png")
|
24
|
+
# => Picasa::Presenter::Photo
|
22
25
|
```
|
23
26
|
|
24
27
|
If password is specified, all requests will be authenticated.
|
25
|
-
This affect results to contain private data.
|
28
|
+
This affect results to contain private data, however it can be controlled by `access` parameter.
|
29
|
+
|
30
|
+
## Caveats
|
31
|
+
|
32
|
+
Currently picasa wont work with `ox` xml parser.
|
33
|
+
Using `rexml` parser wont return `etag` attribute properly.
|
34
|
+
I recommend to use `libxml` or `nokogiri`.
|
35
|
+
|
36
|
+
## Extra
|
37
|
+
|
38
|
+
You can install thor script for uploading all photos from given directory:
|
39
|
+
|
40
|
+
```
|
41
|
+
thor install https://github.com/morgoth/picasa/raw/master/extra/Thorfile --as picasa_uploader --force
|
42
|
+
```
|
43
|
+
|
44
|
+
And then use it (it will create album taking title from folder name and upload all photos from that directory):
|
45
|
+
|
46
|
+
```
|
47
|
+
GOOGLE_USER_ID=your.email@gmail.com GOOGLE_PASSWORD=secret thor picasa_uploader:upload_all path-to-folder-with-photos
|
48
|
+
```
|
26
49
|
|
27
50
|
## Continuous Integration
|
28
51
|
[](http://travis-ci.org/morgoth/picasa)
|
29
52
|
|
30
53
|
## Contributors
|
31
54
|
|
32
|
-
* [Bram Wijnands](https://github.com/
|
55
|
+
* [Bram Wijnands](https://github.com/Bram--)
|
33
56
|
* [Rafael Souza](https://github.com/rafaels)
|
34
57
|
* [jsaak](https://github.com/jsaak)
|
35
58
|
* [Javier Guerra](https://github.com/javierg)
|
data/extra/Thorfile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "picasa"
|
2
|
+
|
3
|
+
# Temporary requirement
|
4
|
+
MultiXml.parser = :libxml
|
5
|
+
|
6
|
+
class PicasaUploader < Thor
|
7
|
+
include Thor::Actions
|
8
|
+
|
9
|
+
desc "upload_all DIR", "Uploads all photos from given directory"
|
10
|
+
def upload_all(dir = File.basename(Dir.getwd))
|
11
|
+
require_credentials
|
12
|
+
album_presenter = create_album(File.basename(dir))
|
13
|
+
photos_number = 0
|
14
|
+
inside(dir, :verbose => true) do
|
15
|
+
Dir.entries(".").select { |e| e =~ /\.(jpg|jpeg|png|gif|bmp)$/i }.sort.each do |file|
|
16
|
+
create_photo(album_presenter, file)
|
17
|
+
photos_number += 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
say "Finished uploading #{photos_number} photos"
|
21
|
+
end
|
22
|
+
|
23
|
+
no_tasks do
|
24
|
+
def require_credentials
|
25
|
+
say "You must specify GOOGLE_USER_ID env variable" and exit unless ENV["GOOGLE_USER_ID"]
|
26
|
+
say "You must specify GOOGLE_PASSWORD env variable" and exit unless ENV["GOOGLE_PASSWORD"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_album(album)
|
30
|
+
say("Creating album: #{album}")
|
31
|
+
client = Picasa::Client.new(user_id: ENV["GOOGLE_USER_ID"], password: ENV["GOOGLE_PASSWORD"])
|
32
|
+
client.album.create(title: album)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_photo(album, path)
|
36
|
+
say("Uploading photo #{path} to album #{album.title}")
|
37
|
+
client = Picasa::Client.new(user_id: ENV["GOOGLE_USER_ID"], password: ENV["GOOGLE_PASSWORD"])
|
38
|
+
client.photo.create(album.id, file_path: path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/picasa.rb
CHANGED
@@ -5,7 +5,11 @@ require "picasa/utils"
|
|
5
5
|
require "picasa/exceptions"
|
6
6
|
require "picasa/connection"
|
7
7
|
require "picasa/client"
|
8
|
+
require "picasa/file"
|
9
|
+
require "picasa/template"
|
10
|
+
|
8
11
|
require "picasa/api/album"
|
12
|
+
require "picasa/api/photo"
|
9
13
|
require "picasa/api/tag"
|
10
14
|
|
11
15
|
require "picasa/presenter/album"
|
data/lib/picasa/api/album.rb
CHANGED
@@ -1,22 +1,15 @@
|
|
1
|
+
require "picasa/api/base"
|
2
|
+
|
1
3
|
module Picasa
|
2
4
|
module API
|
3
|
-
class Album
|
4
|
-
attr_reader :user_id, :credentials
|
5
|
-
|
6
|
-
# @param [Hash] credentials
|
7
|
-
# @option credentials [String] :user_id google username/email
|
8
|
-
# @option credentials [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
|
-
|
5
|
+
class Album < Base
|
17
6
|
# Returns album list
|
18
7
|
#
|
19
8
|
# @param [Hash] options additional options included in request
|
9
|
+
# @option options [all, private, public, visible] :access which data should be retrieved when authenticated
|
10
|
+
# @option options [String] :fields which fields should be retrieved https://developers.google.com/gdata/docs/2.0/reference#PartialResponseRequest
|
11
|
+
# @option options [String, Integer] :max_results how many albums response should include
|
12
|
+
# @option options [String, Integer] :start_index 1-based index of the first result to be retrieved
|
20
13
|
#
|
21
14
|
# @return [Presenter::AlbumList]
|
22
15
|
def list(options = {})
|
@@ -41,6 +34,44 @@ module Picasa
|
|
41
34
|
|
42
35
|
Presenter::Album.new(parsed_body["feed"])
|
43
36
|
end
|
37
|
+
|
38
|
+
# Creates album
|
39
|
+
#
|
40
|
+
# @param [Hash] params album parameters
|
41
|
+
# @option options [String] :title title of album (required)
|
42
|
+
# @option options [String] :summary summary of album
|
43
|
+
# @option options [String] :location location of album photos (i.e. Poland)
|
44
|
+
# @option options [String] :access [public, private, protected]
|
45
|
+
# @option options [String] :timestamp timestamp of album (default to now)
|
46
|
+
# @option options [String] :keywords keywords (i.e. "vacation, poland")
|
47
|
+
#
|
48
|
+
# @return [Presenter::Album]
|
49
|
+
def create(params = {})
|
50
|
+
params[:title] || raise(ArgumentError, "You must specify title")
|
51
|
+
params[:timestamp] ||= Time.now.to_i
|
52
|
+
|
53
|
+
template = Template.new(:new_album, params)
|
54
|
+
uri = URI.parse("/data/feed/api/user/#{user_id}")
|
55
|
+
parsed_body = Connection.new(credentials).post(uri.path, template.render)
|
56
|
+
Presenter::Album.new(parsed_body["entry"])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Destroys given album
|
60
|
+
#
|
61
|
+
# @param [String] album_id album id
|
62
|
+
# @param [Hash] options request parameters
|
63
|
+
# @option options [String] :etag destroys only when ETag matches - protects before destroying other client changes
|
64
|
+
#
|
65
|
+
# @return [true]
|
66
|
+
# @raise [NotFoundError] raised when album cannot be found
|
67
|
+
# @raise [PreconditionFailedError] raised when ETag does not match
|
68
|
+
def destroy(album_id, options = {})
|
69
|
+
headers = {"If-Match" => options.fetch(:etag, "*")}
|
70
|
+
uri = URI.parse("/data/entry/api/user/#{user_id}/albumid/#{album_id}")
|
71
|
+
Connection.new(credentials).delete(uri.path, headers)
|
72
|
+
true
|
73
|
+
end
|
74
|
+
alias :delete :destroy
|
44
75
|
end
|
45
76
|
end
|
46
77
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Picasa
|
2
|
+
module API
|
3
|
+
class Base
|
4
|
+
attr_reader :user_id, :credentials
|
5
|
+
|
6
|
+
# @param [Hash] credentials
|
7
|
+
# @option credentials [String] :user_id google username/email
|
8
|
+
# @option credentials [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
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "picasa/api/base"
|
2
|
+
|
3
|
+
module Picasa
|
4
|
+
module API
|
5
|
+
class Photo < Base
|
6
|
+
# Creates photo for given album
|
7
|
+
#
|
8
|
+
# @param [String] album_id album id
|
9
|
+
# @param [Hash] options request parameters
|
10
|
+
# @option options [String] :file_path path to photo file, rest of required attributes might be guessed based on file (i.e. "/home/john/Images/me.png")
|
11
|
+
# @option options [String] :title title of photo
|
12
|
+
# @option options [String] :summary summary of photo
|
13
|
+
# @option options [String] :binary binary data (i.e. File.open("my-photo.png", "rb").read)
|
14
|
+
# @option options [String] :content_type ["image/jpeg", "image/png", "image/bmp", "image/gif"] content type of given image
|
15
|
+
def create(album_id, params = {})
|
16
|
+
file = params[:file_path] ? File.new(params.delete(:file_path)) : nil
|
17
|
+
params[:boundary] ||= "===============PicasaRubyGem=="
|
18
|
+
params[:title] ||= (file && file.name) || raise(ArgumentError.new("title must be specified"))
|
19
|
+
params[:binary] ||= (file && file.binary) || raise(ArgumentError.new("binary must be specified"))
|
20
|
+
params[:content_type] ||= (file && file.content_type) || raise(ArgumentError.new("content_type must be specified"))
|
21
|
+
template = Template.new(:new_photo, params)
|
22
|
+
headers = {"Content-Type" => "multipart/related; boundary=\"#{params[:boundary]}\""}
|
23
|
+
|
24
|
+
uri = URI.parse("/data/feed/api/user/#{user_id}/albumid/#{album_id}")
|
25
|
+
parsed_body = Connection.new(credentials).post(uri.path, template.render, headers)
|
26
|
+
Presenter::Photo.new(parsed_body["entry"])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/picasa/api/tag.rb
CHANGED
@@ -1,24 +1,13 @@
|
|
1
|
+
require "picasa/api/base"
|
2
|
+
|
1
3
|
module Picasa
|
2
4
|
module API
|
3
|
-
class Tag
|
4
|
-
attr_reader :user_id, :credentials
|
5
|
-
|
6
|
-
# @param [Hash] credentials
|
7
|
-
# @option credentials [String] :user_id google username/email
|
8
|
-
# @option credentials [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
|
-
|
5
|
+
class Tag < Base
|
17
6
|
# Returns tag list - when album_id is not specified, list of user tags will be returned
|
18
7
|
#
|
19
8
|
# @param [Hash] options additional options included in request
|
20
|
-
# @option
|
21
|
-
# @option
|
9
|
+
# @option options [String] :album_id retrieve tags for given album
|
10
|
+
# @option options [String] :photo_id retrieve tags for given photo (album_id must be provided)
|
22
11
|
#
|
23
12
|
# @return [Presenter::TagList]
|
24
13
|
def list(options = {})
|
data/lib/picasa/client.rb
CHANGED
@@ -21,6 +21,17 @@ module Picasa
|
|
21
21
|
API::Album.new(credentials)
|
22
22
|
end
|
23
23
|
|
24
|
+
# @return [API::Photo]
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# client = Picasa::Client.new(user_id: "my.email@google.com", password: "secret")
|
28
|
+
# photo = client.photo.create("album-id", title: "My picture", binary: "image-binary-data", content_type: "image/jpeg")
|
29
|
+
# photo.id
|
30
|
+
# # => "4322232322421"
|
31
|
+
def photo
|
32
|
+
API::Photo.new(credentials)
|
33
|
+
end
|
34
|
+
|
24
35
|
# @return [API::Tag]
|
25
36
|
#
|
26
37
|
# @example
|
data/lib/picasa/connection.rb
CHANGED
@@ -23,6 +23,23 @@ module Picasa
|
|
23
23
|
|
24
24
|
path = path_with_params(path, params)
|
25
25
|
request = Net::HTTP::Get.new(path, headers)
|
26
|
+
response = handle_response(http.request(request))
|
27
|
+
MultiXml.parse(response.body)
|
28
|
+
end
|
29
|
+
|
30
|
+
def post(path, body, custom_headers = {})
|
31
|
+
authenticate if auth?
|
32
|
+
|
33
|
+
request = Net::HTTP::Post.new(path, headers.merge(custom_headers))
|
34
|
+
request.body = body
|
35
|
+
response = handle_response(http.request(request))
|
36
|
+
MultiXml.parse(response.body)
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(path, custom_headers = {})
|
40
|
+
authenticate if auth?
|
41
|
+
|
42
|
+
request = Net::HTTP::Delete.new(path, headers.merge(custom_headers))
|
26
43
|
handle_response(http.request(request))
|
27
44
|
end
|
28
45
|
|
@@ -43,16 +60,24 @@ module Picasa
|
|
43
60
|
def handle_response(response)
|
44
61
|
case response.code.to_i
|
45
62
|
when 200...300
|
46
|
-
|
63
|
+
response
|
64
|
+
when 403
|
65
|
+
raise ForbiddenError.new(response.body, response)
|
47
66
|
when 404
|
48
67
|
raise NotFoundError.new(response.body, response)
|
68
|
+
when 412
|
69
|
+
raise PreconditionFailedError.new(response.body, response)
|
49
70
|
else
|
50
|
-
raise ResponseError.new(
|
71
|
+
raise ResponseError.new(response.body, response)
|
51
72
|
end
|
52
73
|
end
|
53
74
|
|
54
75
|
def headers
|
55
|
-
{
|
76
|
+
{
|
77
|
+
"User-Agent" => client_name,
|
78
|
+
"GData-Version" => API_VERSION,
|
79
|
+
"Content-Type" => "application/atom+xml"
|
80
|
+
}.tap do |headers|
|
56
81
|
headers["Authorization"] = "GoogleLogin auth=#{@auth_key}" if @auth_key
|
57
82
|
end
|
58
83
|
end
|
@@ -61,23 +86,14 @@ module Picasa
|
|
61
86
|
!password.nil?
|
62
87
|
end
|
63
88
|
|
64
|
-
def validate_email!
|
65
|
-
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
|
66
|
-
raise ArgumentError.new("user_id must be a valid E-mail address when authentication is used.")
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
89
|
def authenticate
|
71
|
-
validate_email!
|
72
|
-
|
73
90
|
data = inline_params({"accountType" => "HOSTED_OR_GOOGLE",
|
74
91
|
"Email" => user_id,
|
75
92
|
"Passwd" => password,
|
76
93
|
"service" => "lh2",
|
77
|
-
"source" =>
|
94
|
+
"source" => client_name})
|
78
95
|
|
79
|
-
response = http(API_AUTH_URL).post("/accounts/ClientLogin", data)
|
80
|
-
raise ResponseError.new(response.body, response) unless response.is_a? Net::HTTPSuccess
|
96
|
+
response = handle_response(http(API_AUTH_URL).post("/accounts/ClientLogin", data))
|
81
97
|
|
82
98
|
@auth_key = extract_auth_key(response.body)
|
83
99
|
end
|
@@ -87,5 +103,9 @@ module Picasa
|
|
87
103
|
params = Hash[response]
|
88
104
|
params["Auth"]
|
89
105
|
end
|
106
|
+
|
107
|
+
def client_name
|
108
|
+
"ruby-gem-v#{Picasa::VERSION}"
|
109
|
+
end
|
90
110
|
end
|
91
111
|
end
|
data/lib/picasa/exceptions.rb
CHANGED
data/lib/picasa/file.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Picasa
|
2
|
+
class File
|
3
|
+
attr_reader :path
|
4
|
+
|
5
|
+
def initialize(path)
|
6
|
+
@path = path || raise(ArgumentError.new("path not specified"))
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
@name ||= ::File.basename(path, ".*")
|
11
|
+
end
|
12
|
+
|
13
|
+
def extension
|
14
|
+
@extension ||= ::File.extname(path)[1..-1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def binary
|
18
|
+
@binary ||= ::File.open(path, "rb").read
|
19
|
+
end
|
20
|
+
|
21
|
+
def content_type
|
22
|
+
@content_type ||= case extension
|
23
|
+
when /^jpe?g$/i
|
24
|
+
"image/jpeg"
|
25
|
+
when /^gif$/i
|
26
|
+
"image/gif"
|
27
|
+
when /^png$/i
|
28
|
+
"image/png"
|
29
|
+
when /^bmp$/i
|
30
|
+
"image/bmp"
|
31
|
+
else
|
32
|
+
raise StandarError.new("Content type cannot be guessed from file extension: #{extension}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -16,7 +16,7 @@ module Picasa
|
|
16
16
|
|
17
17
|
# @return [Array<Presenter::Link>]
|
18
18
|
def links
|
19
|
-
@links ||= safe_retrieve(parsed_body, "link").map { |link| Link.new(link) }
|
19
|
+
@links ||= array_wrap(safe_retrieve(parsed_body, "link")).map { |link| Link.new(link) }
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [Presenter::Media]
|
@@ -34,6 +34,11 @@ module Picasa
|
|
34
34
|
@updated ||= map_to_date(safe_retrieve(parsed_body, "updated"))
|
35
35
|
end
|
36
36
|
|
37
|
+
# @return [String]
|
38
|
+
def etag
|
39
|
+
@etag ||= safe_retrieve(parsed_body, "etag")
|
40
|
+
end
|
41
|
+
|
37
42
|
# @return [String]
|
38
43
|
def title
|
39
44
|
@title ||= safe_retrieve(parsed_body, "title")
|
@@ -88,6 +93,16 @@ module Picasa
|
|
88
93
|
def nickname
|
89
94
|
@nickname ||= safe_retrieve(parsed_body, "nickname")
|
90
95
|
end
|
96
|
+
|
97
|
+
# @return [true, false, nil]
|
98
|
+
def allow_prints
|
99
|
+
@allow_prints ||= map_to_boolean(safe_retrieve(parsed_body, "allowPrints"))
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [true, false, nil]
|
103
|
+
def allow_downloads
|
104
|
+
@allow_downloads ||= map_to_boolean(safe_retrieve(parsed_body, "allowDownloads"))
|
105
|
+
end
|
91
106
|
end
|
92
107
|
end
|
93
108
|
end
|
@@ -16,7 +16,7 @@ module Picasa
|
|
16
16
|
|
17
17
|
# @return [Array<Presenter::Link>]
|
18
18
|
def links
|
19
|
-
@links ||= safe_retrieve(parsed_body, "link").map { |link| Link.new(link) }
|
19
|
+
@links ||= array_wrap(safe_retrieve(parsed_body, "link")).map { |link| Link.new(link) }
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [String]
|
@@ -23,6 +23,11 @@ module Picasa
|
|
23
23
|
@id ||= array_wrap(safe_retrieve(parsed_body, "id"))[1]
|
24
24
|
end
|
25
25
|
|
26
|
+
# @return [String]
|
27
|
+
def etag
|
28
|
+
@etag ||= safe_retrieve(parsed_body, "etag")
|
29
|
+
end
|
30
|
+
|
26
31
|
# @return [DateTime]
|
27
32
|
def published
|
28
33
|
@published ||= map_to_date(safe_retrieve(parsed_body, "published"))
|
data/lib/picasa/presenter/tag.rb
CHANGED
@@ -10,7 +10,7 @@ module Picasa
|
|
10
10
|
|
11
11
|
# @return [Array<Presenter::Link>]
|
12
12
|
def links
|
13
|
-
@links ||= safe_retrieve(parsed_body, "link").map { |link| Link.new(link) }
|
13
|
+
@links ||= array_wrap(safe_retrieve(parsed_body, "link")).map { |link| Link.new(link) }
|
14
14
|
end
|
15
15
|
|
16
16
|
# @return [DateTime]
|
@@ -23,6 +23,11 @@ module Picasa
|
|
23
23
|
@title ||= safe_retrieve(parsed_body, "title")
|
24
24
|
end
|
25
25
|
|
26
|
+
# @return [String]
|
27
|
+
def etag
|
28
|
+
@etag ||= safe_retrieve(parsed_body, "etag")
|
29
|
+
end
|
30
|
+
|
26
31
|
# @return [String]
|
27
32
|
def summary
|
28
33
|
@summary ||= safe_retrieve(parsed_body, "summary")
|
@@ -16,7 +16,7 @@ module Picasa
|
|
16
16
|
|
17
17
|
# @return [Array<Presenter::Link>]
|
18
18
|
def links
|
19
|
-
@links ||= safe_retrieve(parsed_body, "link").map { |link| Link.new(link) }
|
19
|
+
@links ||= array_wrap(safe_retrieve(parsed_body, "link")).map { |link| Link.new(link) }
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [String]
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
require "erb"
|
3
|
+
|
4
|
+
module Picasa
|
5
|
+
class Template
|
6
|
+
attr_reader :name, :params
|
7
|
+
|
8
|
+
def initialize(name, params)
|
9
|
+
@name = name
|
10
|
+
@params = params
|
11
|
+
end
|
12
|
+
|
13
|
+
def file
|
14
|
+
@file ||= IO.read(::File.expand_path("../templates/#{name}.xml.erb", __FILE__))
|
15
|
+
end
|
16
|
+
|
17
|
+
def struct
|
18
|
+
@struct ||= OpenStruct.new(params)
|
19
|
+
end
|
20
|
+
|
21
|
+
def render
|
22
|
+
ERB.new(file).result(struct.instance_eval { binding })
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gphoto="http://schemas.google.com/photos/2007">
|
2
|
+
<title type="text"><%= title %></title>
|
3
|
+
<% if summary %>
|
4
|
+
<summary type="text"><%= summary %></summary>
|
5
|
+
<% end %>
|
6
|
+
<% if location %>
|
7
|
+
<gphoto:location><%= location %></gphoto:location>
|
8
|
+
<% end %>
|
9
|
+
<% if access %>
|
10
|
+
<gphoto:access><%= access %></gphoto:access>
|
11
|
+
<% end %>
|
12
|
+
<gphoto:timestamp><%= timestamp %></gphoto:timestamp>
|
13
|
+
<% if keywords %>
|
14
|
+
<media:group>
|
15
|
+
<media:keywords><%= keywords %></media:keywords>
|
16
|
+
</media:group>
|
17
|
+
<% end %>
|
18
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/photos/2007#album"></category>
|
19
|
+
</entry>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
--<%= boundary %>
|
2
|
+
Content-type: application/atom+xml
|
3
|
+
|
4
|
+
<entry xmlns="http://www.w3.org/2005/Atom">
|
5
|
+
<title><%= title %></title>
|
6
|
+
<% if summary %>
|
7
|
+
<summary><%= summary %></summary>
|
8
|
+
<% end %>
|
9
|
+
<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/photos/2007#photo"/>
|
10
|
+
</entry>
|
11
|
+
--<%= boundary %>
|
12
|
+
Content-type: <%= content_type %>
|
13
|
+
|
14
|
+
<%= binary %>
|
15
|
+
--<%= boundary %>
|
data/lib/picasa/utils.rb
CHANGED
data/lib/picasa/version.rb
CHANGED
data/test/api/album_test.rb
CHANGED
@@ -21,4 +21,26 @@ describe Picasa::API::Album do
|
|
21
21
|
assert_equal "Wojciech Wnętrzak", album_show.author.name
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
25
|
+
describe "#create" do
|
26
|
+
it "gives correct parsed body fragment" do
|
27
|
+
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
|
28
|
+
stub_request(:post, "https://picasaweb.google.com/data/feed/api/user/w.wnetrzak@gmail.com").to_return(fixture("album/album-create.txt"))
|
29
|
+
|
30
|
+
album_show = Picasa::API::Album.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret").create(:title => "album")
|
31
|
+
|
32
|
+
assert_equal "Wojciech Wnętrzak", album_show.author.name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#destroy" do
|
37
|
+
it "gives true when success" do
|
38
|
+
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
|
39
|
+
stub_request(:delete, "https://picasaweb.google.com/data/entry/api/user/w.wnetrzak@gmail.com/albumid/123").to_return(:status => 200, :body => "")
|
40
|
+
|
41
|
+
result = Picasa::API::Album.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret").destroy("123")
|
42
|
+
|
43
|
+
assert_equal true, result
|
44
|
+
end
|
45
|
+
end
|
24
46
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require "helper"
|
3
|
+
|
4
|
+
describe Picasa::API::Photo do
|
5
|
+
describe "#create" do
|
6
|
+
it "gives correct parsed body fragment" do
|
7
|
+
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
|
8
|
+
stub_request(:post, "https://picasaweb.google.com/data/feed/api/user/w.wnetrzak@gmail.com/albumid/123").to_return(fixture("photo/photo-created.txt"))
|
9
|
+
|
10
|
+
photo = Picasa::API::Photo.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
|
11
|
+
photo_create = photo.create("123", :title => "test", :binary => "binary", :content_type => "image/png")
|
12
|
+
|
13
|
+
assert_equal 27040, photo_create.size
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises ArgumentError when no title" do
|
17
|
+
photo = Picasa::API::Photo.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
|
18
|
+
assert_raises Picasa::ArgumentError, /title/ do
|
19
|
+
photo.create("123", :binary => "binary", :content_type => "image/png")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "raises ArgumentError when no binary" do
|
24
|
+
photo = Picasa::API::Photo.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
|
25
|
+
assert_raises Picasa::ArgumentError, /binary/ do
|
26
|
+
photo.create("123", :title => "test", :content_type => "image/png")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "raises ArgumentError when no content type" do
|
31
|
+
photo = Picasa::API::Photo.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
|
32
|
+
assert_raises Picasa::ArgumentError, /content_type/ do
|
33
|
+
photo.create("123", :title => "test", :binary => "binary")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "guesses required attributes from file path" do
|
38
|
+
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
|
39
|
+
stub_request(:post, "https://picasaweb.google.com/data/feed/api/user/w.wnetrzak@gmail.com/albumid/123").to_return(fixture("photo/photo-created.txt"))
|
40
|
+
|
41
|
+
photo = Picasa::API::Photo.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
|
42
|
+
|
43
|
+
assert photo.create("123", :file_path => image_path("lena.jpg"))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/test/connection_test.rb
CHANGED
@@ -41,13 +41,25 @@ describe Picasa::Connection do
|
|
41
41
|
connection = Picasa::Connection.new(:user_id => "john.doe@domain.com")
|
42
42
|
uri = URI.parse("/data/feed/api/user/#{connection.user_id}/albumid/non-existing")
|
43
43
|
|
44
|
-
stub_request(:get, "https://picasaweb.google.com" + uri.path).to_return(fixture("not_found.txt"))
|
44
|
+
stub_request(:get, "https://picasaweb.google.com" + uri.path).to_return(fixture("exceptions/not_found.txt"))
|
45
45
|
|
46
46
|
assert_raises Picasa::NotFoundError, "Invalid entity id: non-existing" do
|
47
47
|
connection.get(uri.path)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
it "raises PreconditionFailed exception when 412 returned" do
|
52
|
+
connection = Picasa::Connection.new(:user_id => "john.doe@domain.com", :password => "secret")
|
53
|
+
uri = URI.parse("/data/feed/api/user/#{connection.user_id}/albumid/123")
|
54
|
+
|
55
|
+
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
|
56
|
+
stub_request(:delete, "https://picasaweb.google.com" + uri.path).to_return(fixture("exceptions/precondition_failed.txt"))
|
57
|
+
|
58
|
+
assert_raises Picasa::PreconditionFailedError, "Mismatch: etags = [oldetag], version = [7]" do
|
59
|
+
connection.delete(uri.path, {"If-Match" => "oldetag"})
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
51
63
|
describe "authentication" do
|
52
64
|
it "successfully authenticates" do
|
53
65
|
connection = Picasa::Connection.new(:user_id => "john.doe@domain.com", :password => "secret")
|
@@ -60,21 +72,13 @@ describe Picasa::Connection do
|
|
60
72
|
refute_nil connection.get(uri.path)
|
61
73
|
end
|
62
74
|
|
63
|
-
it "raises ArgumentError when invalid email given" do
|
64
|
-
connection = Picasa::Connection.new(:user_id => "john.doe", :password => "secret")
|
65
|
-
|
66
|
-
assert_raises(Picasa::ArgumentError) do
|
67
|
-
connection.get("/")
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
75
|
it "raises an ResponseError when authentication failed" do
|
72
76
|
connection = Picasa::Connection.new(:user_id => "john.doe@domain.com", :password => "secret")
|
73
77
|
uri = URI.parse("/data/feed/api/user/#{connection.user_id}")
|
74
78
|
|
75
|
-
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("
|
79
|
+
stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("exceptions/forbidden.txt"))
|
76
80
|
|
77
|
-
assert_raises(Picasa::
|
81
|
+
assert_raises(Picasa::ForbiddenError) do
|
78
82
|
connection.get(uri.path)
|
79
83
|
end
|
80
84
|
end
|
data/test/file_test.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Picasa::File do
|
4
|
+
it "raises argument error when nil path given" do
|
5
|
+
assert_raises Picasa::ArgumentError do
|
6
|
+
Picasa::File.new(nil)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "it returns file name" do
|
11
|
+
file = Picasa::File.new(image_path("lena.jpg"))
|
12
|
+
assert_equal "lena", file.name
|
13
|
+
end
|
14
|
+
|
15
|
+
it "it returns file extension" do
|
16
|
+
file = Picasa::File.new(image_path("lena.jpg"))
|
17
|
+
assert_equal "jpg", file.extension
|
18
|
+
end
|
19
|
+
|
20
|
+
it "it guesses content type" do
|
21
|
+
file = Picasa::File.new(image_path("lena.jpg"))
|
22
|
+
assert_equal "image/jpeg", file.content_type
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns binary read file" do
|
26
|
+
file = Picasa::File.new(image_path("lena.jpg"))
|
27
|
+
assert_equal String, file.binary.class
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
HTTP/1.1 201 Created
|
2
|
+
Gdata-version: 2.0
|
3
|
+
Content-length: 2988
|
4
|
+
Via: HTTP/1.1 GWA
|
5
|
+
Content-location: https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5783214424453412737
|
6
|
+
X-content-type-options: nosniff
|
7
|
+
Etag: "YD0qeyI."
|
8
|
+
Set-cookie: _rtok=v2BIV10GEHe2; Path=/; Secure; HttpOnly, S=photos_html=TyVjxRd5Em09qzhPl6Kjsw; Domain=.google.com; Path=/; Secure; HttpOnly
|
9
|
+
Expires: Sat, 01 Sep 2012 14:25:36 GMT
|
10
|
+
Vary: Accept, X-GData-Authorization, GData-Version
|
11
|
+
X-google-cache-control: remote-fetch
|
12
|
+
Server: GSE
|
13
|
+
X-xss-protection: 1; mode=block
|
14
|
+
Location: https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5783214424453412737
|
15
|
+
Cache-control: private, max-age=0, must-revalidate, no-transform
|
16
|
+
Date: Sat, 01 Sep 2012 14:25:36 GMT
|
17
|
+
X-frame-options: SAMEORIGIN
|
18
|
+
Content-type: application/atom+xml; charset=UTF-8; type=entry
|
19
|
+
-content-encoding: gzip
|
20
|
+
|
21
|
+
<?xml version='1.0' encoding='UTF-8'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:gphoto='http://schemas.google.com/photos/2007' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gd='http://schemas.google.com/g/2005' xmlns:gml='http://www.opengis.net/gml' xmlns:georss='http://www.georss.org/georss' gd:etag='"YD0qeyI."'><id>https://picasaweb.google.com/data/entry/user/106136347770555028022/albumid/5783214424453412737</id><published>1970-01-16T14:01:49.000Z</published><updated>2012-09-01T14:25:36.447Z</updated><app:edited>2012-09-01T14:25:36.447Z</app:edited><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#album'/><title>Trip To Poland</title><summary>This was the recent trip I took to Poland.</summary><rights>protected</rights><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://picasaweb.google.com/data/feed/api/user/106136347770555028022/albumid/5783214424453412737'/><link rel='alternate' type='text/html' href='https://picasaweb.google.com/106136347770555028022/TripToPoland'/><link rel='self' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5783214424453412737'/><link rel='edit' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5783214424453412737'/><link rel='http://schemas.google.com/acl/2007#accessControlList' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5783214424453412737/acl'/><author><name>Wojciech Wnętrzak</name><uri>https://picasaweb.google.com/106136347770555028022</uri></author><gphoto:id>5783214424453412737</gphoto:id><gphoto:name>TripToPoland</gphoto:name><gphoto:location>Poland</gphoto:location><gphoto:access>protected</gphoto:access><gphoto:timestamp>1346509000</gphoto:timestamp><gphoto:numphotos>0</gphoto:numphotos><gphoto:numphotosremaining>1000</gphoto:numphotosremaining><gphoto:bytesUsed>0</gphoto:bytesUsed><gphoto:user>106136347770555028022</gphoto:user><gphoto:nickname>Wojciech Wnętrzak</gphoto:nickname><media:group><media:content url='https://lh3.googleusercontent.com/-8od2ksbQgT0/UEIa4NV194E/AAAAAAAAAqI/XIYGNrflH9A/TripToPoland.jpg' type='image/jpeg' medium='image'/><media:credit>Wojciech Wnętrzak</media:credit><media:description type='plain'>This was the recent trip I took to Poland.</media:description><media:keywords/><media:thumbnail url='https://lh3.googleusercontent.com/-8od2ksbQgT0/UEIa4NV194E/AAAAAAAAAqI/XIYGNrflH9A/s160-c/TripToPoland.jpg' height='160' width='160'/><media:title type='plain'>Trip To Poland</media:title></media:group><georss:where><gml:Envelope><gml:lowerCorner>49.0025444 14.1336215</gml:lowerCorner><gml:upperCorner>54.8363315 24.1566505</gml:upperCorner></gml:Envelope><gml:Point><gml:pos>51.919438 19.145136</gml:pos></gml:Point></georss:where></entry>
|
File without changes
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
HTTP/1.1 412 Precondition Failed
|
2
|
+
Expires: Sat, 01 Sep 2012 17:21:46 GMT
|
3
|
+
Date: Sat, 01 Sep 2012 17:21:46 GMT
|
4
|
+
Cache-Control: private, max-age=0, must-revalidate
|
5
|
+
Set-Cookie: _rtok=3ODY353H4sXQ; Path=/; Secure; HttpOnly
|
6
|
+
Set-Cookie: S=photos_html=kOBZzBdZTgXA12OVzxVTbg; Domain=.google.com; Path=/; Secure; HttpOnly
|
7
|
+
Content-Type: text/html; charset=UTF-8
|
8
|
+
X-Content-Type-Options: nosniff
|
9
|
+
X-Frame-Options: SAMEORIGIN
|
10
|
+
X-XSS-Protection: 1; mode=block
|
11
|
+
Server: GSE
|
12
|
+
Transfer-Encoding: chunked
|
13
|
+
|
14
|
+
Mismatch: etags = [oldetag], version = [7]
|
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
HTTP/1.1 201 Created
|
2
|
+
Gdata-version: 2.0
|
3
|
+
Content-length: 3698
|
4
|
+
Via: HTTP/1.1 GWA
|
5
|
+
Content-location: https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834
|
6
|
+
X-content-type-options: nosniff
|
7
|
+
Etag: "YD0qeyI."
|
8
|
+
Set-cookie: _rtok=RJK5U_sWX0B8; Path=/; Secure; HttpOnly, S=photos_html=1MH7BnwEbzDbPVcrJGKtlw; Domain=.google.com; Path=/; Secure; HttpOnly
|
9
|
+
Expires: Fri, 31 Aug 2012 19:19:21 GMT
|
10
|
+
Vary: Accept, X-GData-Authorization, GData-Version
|
11
|
+
X-google-cache-control: remote-fetch
|
12
|
+
Server: GSE
|
13
|
+
X-xss-protection: 1; mode=block
|
14
|
+
Location: https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834
|
15
|
+
Cache-control: private, max-age=0, must-revalidate, no-transform
|
16
|
+
Date: Fri, 31 Aug 2012 19:19:21 GMT
|
17
|
+
X-frame-options: SAMEORIGIN
|
18
|
+
Content-type: application/atom+xml; charset=UTF-8; type=entry
|
19
|
+
-content-encoding: gzip
|
20
|
+
|
21
|
+
<?xml version='1.0' encoding='UTF-8'?><entry xmlns='http://www.w3.org/2005/Atom' xmlns:exif='http://schemas.google.com/photos/exif/2007' xmlns:app='http://www.w3.org/2007/app' xmlns:gphoto='http://schemas.google.com/photos/2007' xmlns:media='http://search.yahoo.com/mrss/' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='"YD0qeyI."'><id>https://picasaweb.google.com/data/entry/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834</id><published>2012-08-31T19:19:20.000Z</published><updated>2012-08-31T19:19:20.882Z</updated><app:edited>2012-08-31T19:19:20.882Z</app:edited><category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#photo'/><title>ancient-test.jpg</title><summary>sent from playground</summary><content type='image/jpeg' src='https://lh5.googleusercontent.com/-HawhXkeW2Y4/UEEOOB0TuUI/AAAAAAAAAos/V1lCZ7oNAEg/ancient-test.jpg'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://picasaweb.google.com/data/feed/api/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834'/><link rel='alternate' type='text/html' href='https://picasaweb.google.com/106136347770555028022/PrivateTesting#5782919030689216834'/><link rel='http://schemas.google.com/photos/2007#canonical' type='text/html' href='https://picasaweb.google.com/lh/photo/HerZrwYwEPv8XgInPPde-NMTjNZETYmyPJy0liipFm0'/><link rel='self' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834'/><link rel='edit' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834'/><link rel='edit-media' type='image/jpeg' href='https://picasaweb.google.com/data/media/api/user/106136347770555028022/albumid/5782912491601845665/photoid/5782919030689216834'/><link rel='http://schemas.google.com/photos/2007#report' type='text/html' href='https://picasaweb.google.com/lh/reportAbuse?uname=106136347770555028022&aid=5782912491601845665&iid=5782919030689216834'/><gphoto:id>5782919030689216834</gphoto:id><gphoto:albumid>5782912491601845665</gphoto:albumid><gphoto:access>only_you</gphoto:access><gphoto:width>473</gphoto:width><gphoto:height>506</gphoto:height><gphoto:size>27040</gphoto:size><gphoto:checksum/><gphoto:timestamp>1346440760000</gphoto:timestamp><gphoto:imageVersion>651</gphoto:imageVersion><gphoto:commentingEnabled>true</gphoto:commentingEnabled><gphoto:commentCount>0</gphoto:commentCount><gphoto:license id='0' name='Wszelkie prawa zastrzeżone' url=''>ALL_RIGHTS_RESERVED</gphoto:license><exif:tags><exif:imageUniqueID>6b5722298561a74e1476868e2ae28b7d</exif:imageUniqueID></exif:tags><media:group><media:content url='https://lh5.googleusercontent.com/-HawhXkeW2Y4/UEEOOB0TuUI/AAAAAAAAAos/V1lCZ7oNAEg/ancient-test.jpg' height='506' width='473' type='image/jpeg' medium='image'/><media:credit>Wojciech Wnętrzak</media:credit><media:description type='plain'>sent from playground</media:description><media:keywords/><media:thumbnail url='https://lh5.googleusercontent.com/-HawhXkeW2Y4/UEEOOB0TuUI/AAAAAAAAAos/V1lCZ7oNAEg/s72/ancient-test.jpg' height='72' width='68'/><media:thumbnail url='https://lh5.googleusercontent.com/-HawhXkeW2Y4/UEEOOB0TuUI/AAAAAAAAAos/V1lCZ7oNAEg/s144/ancient-test.jpg' height='144' width='135'/><media:thumbnail url='https://lh5.googleusercontent.com/-HawhXkeW2Y4/UEEOOB0TuUI/AAAAAAAAAos/V1lCZ7oNAEg/s288/ancient-test.jpg' height='288' width='270'/><media:title type='plain'>ancient-test.jpg</media:title></media:group></entry>
|
data/test/helper.rb
CHANGED
@@ -14,6 +14,10 @@ class MiniTest::Unit::TestCase
|
|
14
14
|
WebMock.disable_net_connect!
|
15
15
|
end
|
16
16
|
|
17
|
+
def image_path(filename)
|
18
|
+
::File.join("test", "fixtures", filename)
|
19
|
+
end
|
20
|
+
|
17
21
|
# Recording response is as simple as writing in terminal:
|
18
22
|
# curl -is -H "GData-Version: 2" "https://picasaweb.google.com/data/feed/api/user/username?prettyprint=true" -X GET > test/fixtures/albums.txt
|
19
23
|
def fixture(filename)
|
@@ -20,6 +20,10 @@ describe Picasa::Presenter::Album do
|
|
20
20
|
assert_equal 3, @album.links.size
|
21
21
|
end
|
22
22
|
|
23
|
+
it "has etag" do
|
24
|
+
assert_equal "\"YDkqeyI.\"", @album.etag
|
25
|
+
end
|
26
|
+
|
23
27
|
it "has media credit" do
|
24
28
|
assert_equal "Wojciech Wnętrzak", @album.media.credit
|
25
29
|
end
|
@@ -127,6 +131,10 @@ describe Picasa::Presenter::Album do
|
|
127
131
|
assert_equal "5243667126168669553", @album.id
|
128
132
|
end
|
129
133
|
|
134
|
+
it "has etag" do
|
135
|
+
assert_equal "W/\"DUICQX0_fSp7ImA9WhdSGEo.\"", @album.etag
|
136
|
+
end
|
137
|
+
|
130
138
|
it "has name" do
|
131
139
|
assert_equal "Test2", @album.name
|
132
140
|
end
|
@@ -158,6 +166,14 @@ describe Picasa::Presenter::Album do
|
|
158
166
|
it "has photo entries" do
|
159
167
|
assert_equal 3, @album.entries.size
|
160
168
|
end
|
169
|
+
|
170
|
+
it "has allow_prints" do
|
171
|
+
assert_equal true, @album.allow_prints
|
172
|
+
end
|
173
|
+
|
174
|
+
it "has allow_downloads" do
|
175
|
+
assert_equal true, @album.allow_downloads
|
176
|
+
end
|
161
177
|
end
|
162
178
|
|
163
179
|
describe "album from show with single photo" do
|
data/test/presenter/tag_test.rb
CHANGED
@@ -24,6 +24,10 @@ describe Picasa::Presenter::Tag do
|
|
24
24
|
assert_equal "2012-08-17T08:40:24+00:00", @tag.updated.to_s
|
25
25
|
end
|
26
26
|
|
27
|
+
it "has etag" do
|
28
|
+
assert_equal "W/\"CE8GRXczfip7ImA9WhJWEUQ.\"", @tag.etag
|
29
|
+
end
|
30
|
+
|
27
31
|
it "has title" do
|
28
32
|
assert_equal "nice", @tag.title
|
29
33
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Picasa::Template do
|
4
|
+
it "has name" do
|
5
|
+
template = Picasa::Template.new(:new_album, {})
|
6
|
+
assert_equal :new_album, template.name
|
7
|
+
end
|
8
|
+
|
9
|
+
it "has params" do
|
10
|
+
template = Picasa::Template.new(:new_album, {:title => "My album"})
|
11
|
+
assert_equal({:title => "My album"}, template.params)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "new_album" do
|
15
|
+
it "renders title" do
|
16
|
+
template = Picasa::Template.new(:new_album, {:title => "My album"})
|
17
|
+
assert_match %q{<title type="text">My album</title>}, template.render
|
18
|
+
end
|
19
|
+
|
20
|
+
it "renders summary" do
|
21
|
+
template = Picasa::Template.new(:new_album, {:summary => "My summary"})
|
22
|
+
assert_match %q{<summary type="text">My summary</summary>}, template.render
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: picasa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_xml
|
@@ -72,12 +72,16 @@ files:
|
|
72
72
|
- LICENSE
|
73
73
|
- README.md
|
74
74
|
- Rakefile
|
75
|
+
- extra/Thorfile
|
75
76
|
- lib/picasa.rb
|
76
77
|
- lib/picasa/api/album.rb
|
78
|
+
- lib/picasa/api/base.rb
|
79
|
+
- lib/picasa/api/photo.rb
|
77
80
|
- lib/picasa/api/tag.rb
|
78
81
|
- lib/picasa/client.rb
|
79
82
|
- lib/picasa/connection.rb
|
80
83
|
- lib/picasa/exceptions.rb
|
84
|
+
- lib/picasa/file.rb
|
81
85
|
- lib/picasa/presenter/album.rb
|
82
86
|
- lib/picasa/presenter/album_list.rb
|
83
87
|
- lib/picasa/presenter/author.rb
|
@@ -89,23 +93,32 @@ files:
|
|
89
93
|
- lib/picasa/presenter/tag.rb
|
90
94
|
- lib/picasa/presenter/tag_list.rb
|
91
95
|
- lib/picasa/presenter/thumbnail.rb
|
96
|
+
- lib/picasa/template.rb
|
97
|
+
- lib/picasa/templates/new_album.xml.erb
|
98
|
+
- lib/picasa/templates/new_photo.xml.erb
|
92
99
|
- lib/picasa/utils.rb
|
93
100
|
- lib/picasa/version.rb
|
94
101
|
- picasa.gemspec
|
95
102
|
- test/api/album_test.rb
|
103
|
+
- test/api/photo_test.rb
|
96
104
|
- test/api/tag_test.rb
|
97
105
|
- test/client_test.rb
|
98
106
|
- test/connection_test.rb
|
107
|
+
- test/file_test.rb
|
108
|
+
- test/fixtures/album/album-create.txt
|
99
109
|
- test/fixtures/album/album-list-with-tag.txt
|
100
110
|
- test/fixtures/album/album-list.txt
|
101
111
|
- test/fixtures/album/album-show-with-max-results.txt
|
102
112
|
- test/fixtures/album/album-show-with-tag-and-many-photos.txt
|
103
113
|
- test/fixtures/album/album-show-with-tag-and-one-photo.txt
|
104
114
|
- test/fixtures/album/album-show.txt
|
105
|
-
- test/fixtures/auth/failure.txt
|
106
115
|
- test/fixtures/auth/success.txt
|
116
|
+
- test/fixtures/exceptions/forbidden.txt
|
117
|
+
- test/fixtures/exceptions/not_found.txt
|
118
|
+
- test/fixtures/exceptions/precondition_failed.txt
|
107
119
|
- test/fixtures/json.txt
|
108
|
-
- test/fixtures/
|
120
|
+
- test/fixtures/lena.jpg
|
121
|
+
- test/fixtures/photo/photo-created.txt
|
109
122
|
- test/fixtures/photo/photo-list-all-with-q.txt
|
110
123
|
- test/fixtures/photo/photo-list-all.txt
|
111
124
|
- test/fixtures/photo/photo-list-user.txt
|
@@ -126,6 +139,7 @@ files:
|
|
126
139
|
- test/presenter/tag_list_test.rb
|
127
140
|
- test/presenter/tag_test.rb
|
128
141
|
- test/presenter/thumbnail_test.rb
|
142
|
+
- test/template_test.rb
|
129
143
|
- test/utils_test.rb
|
130
144
|
homepage: https://github.com/morgoth/picasa
|
131
145
|
licenses: []
|