picasa 0.5.2 → 0.5.3

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/Gemfile CHANGED
@@ -4,7 +4,7 @@ gemspec
4
4
 
5
5
  gem "thor"
6
6
  gem "rake"
7
- gem "minitest", :platform => :ruby_18
7
+ gem "minitest", "3.5.0", :platform => :ruby_18
8
8
  gem "debugger", :platform => :ruby_19
9
9
 
10
10
  # xml parsers
data/README.md CHANGED
@@ -45,30 +45,34 @@ client = Picasa::Client.new(user_id: "some.user@gmail.com", authorization_header
45
45
  You can install thor script for uploading all photos from given directory:
46
46
 
47
47
  ```
48
- thor install https://github.com/morgoth/picasa/raw/master/extra/Thorfile --as picasa_uploader --force
48
+ thor install https://github.com/morgoth/picasa/raw/master/extra/Thorfile --as imagery --force
49
49
  ```
50
50
 
51
51
  Updating script can be done by:
52
52
 
53
53
  ```
54
- thor update picasa_uploader
54
+ thor update imagery
55
55
  ```
56
56
 
57
57
  And then use it (it will create album taking title from folder name and upload all photos from that directory):
58
58
 
59
59
  ```
60
- GOOGLE_USER_ID=your.email@gmail.com GOOGLE_PASSWORD=secret thor picasa_uploader:upload_all path-to-folder-with-photos
60
+ GOOGLE_USER_ID=your.email@gmail.com GOOGLE_PASSWORD=secret thor imagery:upload path-to-folder-with-photos
61
61
  # Without specifing password
62
- GOOGLE_USER_ID=your.email@gmail.com GOOGLE_AUTHORIZATION_HEADER="GoogleLogin auth=token" thor picasa_uploader:upload_all path-to-folder-with-photos
62
+ GOOGLE_USER_ID=your.email@gmail.com GOOGLE_AUTHORIZATION_HEADER="GoogleLogin auth=token" thor imagery:upload path-to-folder-with-photos
63
63
  ```
64
64
 
65
65
  If your upload was somehow interrupted, you can resume it by adding `--continue` option:
66
66
 
67
67
  ```
68
- GOOGLE_USER_ID=your.email@gmail.com GOOGLE_PASSWORD=secret thor picasa_uploader:upload_all --continue path-to-folder-with-photos
68
+ GOOGLE_USER_ID=your.email@gmail.com GOOGLE_PASSWORD=secret thor imagery:upload --continue path-to-folder-with-photos
69
69
  ```
70
70
 
71
- If you run out of quota and want to resize images to fit Picasa free storage limits, you might be interested in Thor task for [that job](https://github.com/morgoth/ripper#usage)
71
+ If you run out of quota and want to resize images to fit Picasa free storage limits, you can install `rmagick` gem and run (this will modify files):
72
+
73
+ ```
74
+ thor imagery:resize path-to-folder-with-photos
75
+ ```
72
76
 
73
77
  ## Caveats
74
78
 
@@ -77,6 +81,11 @@ Currently picasa wont work with `ox` xml parser.
77
81
  Using `rexml` parser wont return `etag` attribute properly.
78
82
 
79
83
  I recommend to use `libxml` or `nokogiri`.
84
+ You can set it by:
85
+
86
+ ```ruby
87
+ MultiXml.parser = :libxml
88
+ ```
80
89
 
81
90
  ## Continuous Integration
82
91
  [![Build Status](https://secure.travis-ci.org/morgoth/picasa.png)](http://travis-ci.org/morgoth/picasa)
File without changes
@@ -4,9 +4,10 @@ begin
4
4
  client = Picasa::Client.new(:user_id => "your_gmail_account", :password => "password")
5
5
  # create new album.
6
6
  client.album.create(
7
- :title => "New Album",
8
- :summary => "This is a new album.",
9
- :access => "protected")
7
+ :title => "New Album",
8
+ :summary => "This is a new album.",
9
+ :access => "protected"
10
+ )
10
11
 
11
12
  rescue Picasa::ForbiddenError
12
13
  puts "You have the wrong user_id or password."
File without changes
@@ -0,0 +1,41 @@
1
+ # Download photos example
2
+ # Matthew Epler, Sept 2012
3
+
4
+ require "picasa"
5
+ require "open-uri"
6
+
7
+ username = "user@gmail.com"
8
+ dir = "/Users/path.../"
9
+
10
+ begin
11
+ client = Picasa::Client.new(:user_id => username)
12
+ albums = client.album.list.entries
13
+
14
+ albums.each do |album|
15
+ Dir.chdir(dir)
16
+ this_album = client.album.show(album.id).entries
17
+ Dir.mkdir(album.title)
18
+ Dir.chdir(album.title)
19
+
20
+ for photo in this_album
21
+ begin
22
+ get_string = photo.content.src
23
+ puts "processing" << photo.id
24
+
25
+ rescue Exception => e
26
+ puts photo.id << " **ERROR**"
27
+ puts e
28
+ end
29
+
30
+ open(get_string) do |f|
31
+ File.open(photo.title, "wb") do |file|
32
+ file.puts f.read
33
+ end
34
+ end
35
+ puts "======================================"
36
+ end
37
+ end
38
+
39
+ rescue Picasa::ForbiddenError
40
+ puts "You have the wrong user_id or password."
41
+ end
@@ -0,0 +1,37 @@
1
+ # Download photos example
2
+ # Matthew Epler, Sept 2012
3
+
4
+ require "picasa"
5
+ require "open-uri"
6
+
7
+ username = "user@gmail.com"
8
+ dir = "/Users/path.../"
9
+
10
+ begin
11
+ client = Picasa::Client.new(:user_id => username)
12
+ albums = client.album.list.entries
13
+
14
+ album = albums.find { |album| album.title == "your_album_name" }
15
+ photos = client.album.show(album.id).entries
16
+
17
+ photos.each do |photo|
18
+ begin
19
+ get_string = photo.content.src
20
+ puts "processing " << photo.id
21
+
22
+ rescue Exception => e
23
+ puts photo.id << " **ERROR**"
24
+ puts e
25
+
26
+ Dir.chdir(dir)
27
+ open(get_string) do |f|
28
+ File.open(photo.title, "wb") do |file|
29
+ file.puts f.read
30
+ end
31
+ end
32
+ puts "======================================"
33
+ end
34
+ end
35
+ rescue Picasa::ForbiddenError
36
+ puts "You have the wrong user_id or password."
37
+ end
File without changes
File without changes
File without changes
data/extra/Thorfile CHANGED
@@ -4,13 +4,13 @@ require "thread"
4
4
  # Temporary requirement
5
5
  MultiXml.parser = :libxml
6
6
 
7
- class PicasaUploader < Thor
7
+ class Imagery < Thor
8
8
  include Thor::Actions
9
9
 
10
- desc "upload_all DIR", "Uploads all photos from given directory (pass --continue to resume uploading)"
10
+ desc "upload [-c] [-t <number>] DIR", "Uploads all photos from given directory (pass --continue to continue uploading)"
11
11
  method_option :continue, type: :boolean, default: false, aliases: "-c", desc: "continue aborted upload"
12
12
  method_option :threads, type: :numeric, default: 8, aliases: "-t", desc: "specify threads number"
13
- def upload_all(dir = File.basename(Dir.getwd))
13
+ def upload(dir = File.basename(Dir.getwd))
14
14
  require_credentials
15
15
 
16
16
  inside(dir, verbose: true) do
@@ -52,6 +52,33 @@ class PicasaUploader < Thor
52
52
  end
53
53
  end
54
54
 
55
+ desc "resize [-w <number>] [-h <number>] DIR", "Resizes photos to given dimensions if exceeded"
56
+ method_option :width, type: :numeric, default: 2048, aliases: "-w", desc: "max width"
57
+ method_option :height, type: :numeric, default: 2048, aliases: "-h", desc: "max height"
58
+ def resize(dir = ".")
59
+ # Requires imagemagick library
60
+ require "RMagick"
61
+ inside(dir, verbose: true) do
62
+ entries = Dir.entries(".").select { |e| e =~ /\.(jpg|jpeg|png|gif|bmp)$/i }.sort
63
+ processed = 0
64
+ entries.each do |file|
65
+ photo = Magick::Image.read(file).first
66
+ processed += 1
67
+ GC.start # problems with memory leaking by RMagick
68
+ if photo.columns > options[:width] || photo.rows > options[:height]
69
+ say "Resizing #{file} to fit #{options[:width]}x#{options[:height]} - #{processed}/#{entries.size}"
70
+
71
+ photo.resize_to_fit!(options[:width], options[:height])
72
+ photo.write(File.basename(file))
73
+ # Release memory
74
+ photo.destroy!
75
+ else
76
+ say "Skipping #{file} - #{processed}/#{entries.size}"
77
+ end
78
+ end
79
+ end
80
+ end
81
+
55
82
  no_tasks do
56
83
  def client
57
84
  @client ||= Picasa::Client.new(user_id: ENV["GOOGLE_USER_ID"],
data/lib/picasa.rb CHANGED
@@ -9,12 +9,15 @@ require "picasa/file"
9
9
  require "picasa/template"
10
10
 
11
11
  require "picasa/api/album"
12
+ require "picasa/api/comment"
12
13
  require "picasa/api/photo"
13
14
  require "picasa/api/tag"
14
15
 
15
16
  require "picasa/presenter/album"
16
17
  require "picasa/presenter/album_list"
17
18
  require "picasa/presenter/author"
19
+ require "picasa/presenter/comment"
20
+ require "picasa/presenter/comment_list"
18
21
  require "picasa/presenter/content"
19
22
  require "picasa/presenter/link"
20
23
  require "picasa/presenter/media"
@@ -0,0 +1,70 @@
1
+ require "picasa/api/base"
2
+
3
+ module Picasa
4
+ module API
5
+ class Comment < Base
6
+ # Returns comment list - when album_id is not specified, list of user comments will be returned
7
+ #
8
+ # @param [Hash] options additional options included in request
9
+ # @option options [String] :album_id retrieve comments for given album
10
+ # @option options [String] :photo_id retrieve comments for given photo (album_id must be provided)
11
+ #
12
+ # @return [Presenter::CommentList]
13
+ def list(options = {})
14
+ album_id = options.delete(:album_id)
15
+ photo_id = options.delete(:photo_id)
16
+ raise(ArgumentError, "You must specify album_id when providing photo_id") if photo_id && !album_id
17
+
18
+ path = "/data/feed/api/user/#{user_id}"
19
+ path << "/albumid/#{album_id}" if album_id
20
+ path << "/photoid/#{photo_id}" if photo_id
21
+
22
+ uri = URI.parse(path)
23
+ response = Connection.new.get(:path => uri.path, :query => options.merge(:kind => "comment"), :headers => auth_header)
24
+
25
+ Presenter::CommentList.new(MultiXml.parse(response.body)["feed"])
26
+ end
27
+
28
+ # Creates a comment for a photo.
29
+ #
30
+ # @param [Hash]
31
+ # @option options [String] :album_id id of album
32
+ # @option options [String] :photo_id id of photo
33
+ # @option options [String] :content name of tag
34
+ #
35
+ # @return [Presenter::Tag]
36
+ def create(params = {})
37
+ album_id = params.delete(:album_id) || raise(ArgumentError, "You must specify album_id")
38
+ photo_id = params.delete(:photo_id) || raise(ArgumentError, "You must specify photo_id")
39
+ params[:content] || raise(ArgumentError, "You must specify content")
40
+
41
+ path = "/data/feed/api/user/#{user_id}/albumid/#{album_id}/photoid/#{photo_id}"
42
+
43
+ template = Template.new("new_comment", params)
44
+
45
+ uri = URI.parse(path)
46
+ response = Connection.new.post(:path => uri.path, :body => template.render, :headers => auth_header)
47
+
48
+ Presenter::Comment.new(MultiXml.parse(response.body)["entry"])
49
+ end
50
+
51
+ # Removes a comment from given photo.
52
+ #
53
+ # @param [String] comment_id comment id
54
+ # @param [Hash]
55
+ # @option options [String] :album_id id of album
56
+ # @option options [String] :photo_id id of photo
57
+ #
58
+ # @return [true]
59
+ def destroy(comment_id, params = {})
60
+ album_id = params.delete(:album_id) || raise(ArgumentError, "You must specify album_id")
61
+ photo_id = params.delete(:photo_id) || raise(ArgumentError, "You must specify photo_id")
62
+
63
+ uri = URI.parse("/data/entry/api/user/#{user_id}/albumid/#{album_id}/photoid/#{photo_id}/commentid/#{comment_id}")
64
+ Connection.new.delete(:path => uri.path, :headers => auth_header)
65
+ true
66
+ end
67
+ alias :delete :destroy
68
+ end
69
+ end
70
+ end
@@ -28,10 +28,10 @@ module Picasa
28
28
  Presenter::Photo.new(MultiXml.parse(response.body)["entry"])
29
29
  end
30
30
 
31
- # Destroys given photo
31
+ # Destroys given photo
32
32
  #
33
33
  # @param [String] album_id album id
34
- # @param [String] photo_id photo id
34
+ # @param [String] photo_id photo id
35
35
  # @param [Hash] options request parameters
36
36
  # @option options [String] :etag destroys only when ETag matches - protects before destroying other client changes
37
37
  #
@@ -28,7 +28,7 @@ module Picasa
28
28
  # Creates a tag for a photo.
29
29
  #
30
30
  # @param [Hash]
31
- # @option options [String] :album_id id pof album
31
+ # @option options [String] :album_id id of album
32
32
  # @option options [String] :photo_id id of photo
33
33
  # @option options [String] :title name of tag
34
34
  #
@@ -47,6 +47,24 @@ module Picasa
47
47
 
48
48
  Presenter::Tag.new(MultiXml.parse(response.body)["entry"])
49
49
  end
50
+
51
+ # Removes a tag from given photo.
52
+ #
53
+ # @param [String] tag_id tag name (title)
54
+ # @param [Hash]
55
+ # @option options [String] :album_id id pof album
56
+ # @option options [String] :photo_id id of photo
57
+ #
58
+ # @return [true]
59
+ def destroy(tag_id, params = {})
60
+ album_id = params.delete(:album_id) || raise(ArgumentError, "You must specify album_id")
61
+ photo_id = params.delete(:photo_id) || raise(ArgumentError, "You must specify photo_id")
62
+
63
+ uri = URI.parse("/data/entry/api/user/#{user_id}/albumid/#{album_id}/photoid/#{photo_id}/tag/#{tag_id}")
64
+ Connection.new.delete(:path => uri.path, :headers => auth_header)
65
+ true
66
+ end
67
+ alias :delete :destroy
50
68
  end
51
69
  end
52
70
  end
data/lib/picasa/client.rb CHANGED
@@ -48,6 +48,18 @@ module Picasa
48
48
  API::Tag.new(credentials)
49
49
  end
50
50
 
51
+ # @return [API::Comment]
52
+ #
53
+ # @example
54
+ # client = Picasa::Client.new(user_id: "my.email@google.com")
55
+ # comment_list = client.comment.list(album_id: "988", photo_id: "123")
56
+ # comment_list.entries.map &:content
57
+ # # => "nice photo!"
58
+ def comment
59
+ authenticate if authenticates?
60
+ API::Comment.new(credentials)
61
+ end
62
+
51
63
  # @return [String]
52
64
  def authenticate
53
65
  response = Connection.new.post(
@@ -1,44 +1,46 @@
1
1
  require "net/https"
2
- require "cgi"
3
2
  require "uri"
4
3
 
5
4
  module Picasa
6
5
  class Connection
7
- def http(url = API_URL)
8
- uri = URI.parse(url)
9
- http = Net::HTTP.new(uri.host, uri.port)
10
- http.use_ssl = true
11
- http
12
- end
13
-
14
6
  # @param [Hash] params request arguments
15
7
  # @option params [String] :host host of request
16
8
  # @option params [String] :path request path
17
- # @option params [String] :body request body (for POST)
18
9
  # @option params [String] :query request url query
19
10
  # @option params [String] :headers request headers
20
11
  def get(params = {})
12
+ params[:host] ||= API_URL
21
13
  params[:headers] ||= {}
22
- params[:query] ||= {}
23
- params[:host] ||= API_URL
14
+ params[:query] ||= {}
24
15
 
25
16
  path = path_with_query(params[:path], params[:query])
26
17
  request = Net::HTTP::Get.new(path, headers.merge(params[:headers]))
27
18
  handle_response(http(params[:host]).request(request))
28
19
  end
29
20
 
21
+ # @param [Hash] params request arguments
22
+ # @option params [String] :host host of request
23
+ # @option params [String] :path request path
24
+ # @option params [String] :body request body (for POST)
25
+ # @option params [String] :query request url query
26
+ # @option params [String] :headers request headers
30
27
  def post(params = {})
28
+ params[:host] ||= API_URL
31
29
  params[:headers] ||= {}
32
- params[:host] ||= API_URL
33
30
 
34
31
  request = Net::HTTP::Post.new(params[:path], headers.merge(params[:headers]))
35
32
  request.body = params[:body]
36
33
  handle_response(http(params[:host]).request(request))
37
34
  end
38
35
 
36
+ # @param [Hash] params request arguments
37
+ # @option params [String] :host host of request
38
+ # @option params [String] :path request path
39
+ # @option params [String] :query request url query
40
+ # @option params [String] :headers request headers
39
41
  def delete(params = {})
42
+ params[:host] ||= API_URL
40
43
  params[:headers] ||= {}
41
- params[:host] ||= API_URL
42
44
 
43
45
  request = Net::HTTP::Delete.new(params[:path], headers.merge(params[:headers]))
44
46
  handle_response(http(params[:host]).request(request))
@@ -51,6 +53,13 @@ module Picasa
51
53
 
52
54
  private
53
55
 
56
+ def http(url = API_URL)
57
+ uri = URI.parse(url)
58
+ http = Net::HTTP.new(uri.host, uri.port)
59
+ http.use_ssl = true
60
+ http
61
+ end
62
+
54
63
  def handle_response(response)
55
64
  case response.code.to_i
56
65
  when 200...300
@@ -0,0 +1,57 @@
1
+ require "picasa/presenter/base"
2
+
3
+ module Picasa
4
+ module Presenter
5
+ class Comment < Base
6
+ # @return [Presenter::Author]
7
+ def author
8
+ @author ||= Author.new(safe_retrieve(parsed_body, "author"))
9
+ end
10
+
11
+ # @return [Array<Presenter::Link>]
12
+ def links
13
+ @links ||= array_wrap(safe_retrieve(parsed_body, "link")).map { |link| Link.new(link) }
14
+ end
15
+
16
+ # @return [DateTime]
17
+ def published
18
+ @published ||= map_to_date(safe_retrieve(parsed_body, "published"))
19
+ end
20
+
21
+ # @return [DateTime]
22
+ def updated
23
+ @updated ||= map_to_date(safe_retrieve(parsed_body, "updated"))
24
+ end
25
+
26
+ # @return [DateTime]
27
+ def edited
28
+ @edited ||= map_to_date(safe_retrieve(parsed_body, "edited"))
29
+ end
30
+
31
+ # @return [String]
32
+ def title
33
+ @title ||= safe_retrieve(parsed_body, "title")
34
+ end
35
+
36
+ # @return [String]
37
+ def etag
38
+ @etag ||= safe_retrieve(parsed_body, "etag")
39
+ end
40
+
41
+ # @return [String]
42
+ def content
43
+ @content ||= safe_retrieve(parsed_body, "content", "__content__") || safe_retrieve(parsed_body, "content")
44
+ end
45
+
46
+ # @return [String]
47
+ def id
48
+ @id ||= array_wrap(safe_retrieve(parsed_body, "id")).last
49
+ end
50
+
51
+ # @return [String]
52
+ def photo_id
53
+ @photo_id ||= safe_retrieve(parsed_body, "photoid")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,73 @@
1
+ require "picasa/presenter/base"
2
+
3
+ module Picasa
4
+ module Presenter
5
+ class CommentList < Base
6
+ # @return [Presenter::Author]
7
+ def author
8
+ @author ||= Author.new(safe_retrieve(parsed_body, "author"))
9
+ end
10
+
11
+ # @return [Array<Presenter::Comment>]
12
+ def entries
13
+ @entries ||= array_wrap(safe_retrieve(parsed_body, "entry")).map { |entry| Comment.new(entry) }
14
+ end
15
+ alias :comments :entries
16
+
17
+ # @return [Array<Presenter::Link>]
18
+ def links
19
+ @links ||= array_wrap(safe_retrieve(parsed_body, "link")).map { |link| Link.new(link) }
20
+ end
21
+
22
+ # @return [String]
23
+ def title
24
+ @title ||= safe_retrieve(parsed_body, "title")
25
+ end
26
+
27
+ # @return [DateTime]
28
+ def updated
29
+ @updated ||= map_to_date(safe_retrieve(parsed_body, "updated"))
30
+ end
31
+
32
+ # @return [String]
33
+ def icon
34
+ @icon ||= safe_retrieve(parsed_body, "icon")
35
+ end
36
+
37
+ # @return [String]
38
+ def generator
39
+ @generator ||= safe_retrieve(parsed_body, "generator", "__content__")
40
+ end
41
+
42
+ # @return [Integer]
43
+ def total_results
44
+ @total_results ||= map_to_integer(safe_retrieve(parsed_body, "totalResults"))
45
+ end
46
+
47
+ # @return [Integer]
48
+ def start_index
49
+ @start_index ||= map_to_integer(safe_retrieve(parsed_body, "startIndex"))
50
+ end
51
+
52
+ # @return [Integer]
53
+ def items_per_page
54
+ @items_per_page ||= map_to_integer(safe_retrieve(parsed_body, "itemsPerPage"))
55
+ end
56
+
57
+ # @return [String]
58
+ def user
59
+ @user ||= safe_retrieve(parsed_body, "user")
60
+ end
61
+
62
+ # @return [String]
63
+ def nickname
64
+ @nickname ||= safe_retrieve(parsed_body, "nickname")
65
+ end
66
+
67
+ # @return [String]
68
+ def thumbnail
69
+ @thumbnail ||= safe_retrieve(parsed_body, "thumbnail")
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,4 @@
1
+ <entry xmlns="http://www.w3.org/2005/Atom">
2
+ <content><%= content %></content>
3
+ <category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/photos/2007#comment"/>
4
+ </entry>
data/lib/picasa/utils.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "date"
2
+ require "cgi"
2
3
 
3
4
  module Picasa
4
5
  module Utils
@@ -1,3 +1,3 @@
1
1
  module Picasa
2
- VERSION = "0.5.2"
2
+ VERSION = "0.5.3"
3
3
  end
@@ -0,0 +1,70 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "helper"
3
+
4
+ describe Picasa::API::Comment do
5
+ describe "#list" do
6
+ it "throws ArgumentError when photo_id provided without album_id" do
7
+ comment = Picasa::API::Comment.new(:user_id => "w.wnetrzak")
8
+
9
+ assert_raises Picasa::ArgumentError, /album_id/ do
10
+ comment.list(:photo_id => "12343")
11
+ end
12
+ end
13
+
14
+ it "gives correct parsed body fragment" do
15
+ stub_request(:get, "https://picasaweb.google.com/data/feed/api/user/w.wnetrzak?kind=comment").to_return(fixture("comment/comment-list.txt"))
16
+
17
+ comment_list = Picasa::API::Comment.new(:user_id => "w.wnetrzak").list
18
+
19
+ assert_equal 1, comment_list.entries.size
20
+ end
21
+ end
22
+
23
+ describe "#create" do
24
+ it "raises ArgumentError when no album_id" do
25
+ comment = Picasa::API::Comment.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
26
+ assert_raises Picasa::ArgumentError, /album_id/ do
27
+ comment.create(:photo_id => "455", :content => "content")
28
+ end
29
+ end
30
+
31
+ it "raises ArgumentError when no photo_id" do
32
+ comment = Picasa::API::Comment.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
33
+ assert_raises Picasa::ArgumentError, /photo_id/ do
34
+ comment.create(:album_id => "123", :content => "content")
35
+ end
36
+ end
37
+
38
+ it "raises ArgumentError when no content" do
39
+ comment = Picasa::API::Comment.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
40
+ assert_raises Picasa::ArgumentError, /content/ do
41
+ comment.create(:album_id => "123", :photo_id => "455")
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#destroy" do
47
+ it "raises ArgumentError when no photo_id" do
48
+ comment = Picasa::API::Comment.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
49
+ assert_raises Picasa::ArgumentError, /photo_id/ do
50
+ comment.destroy("wtf", :album_id => "123")
51
+ end
52
+ end
53
+
54
+ it "raises ArgumentError when no album_id" do
55
+ comment = Picasa::API::Comment.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
56
+ assert_raises Picasa::ArgumentError, /album_id/ do
57
+ comment.destroy("wtf", :photo_id => "455")
58
+ end
59
+ end
60
+
61
+ it "gives true when success" do
62
+ stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
63
+ stub_request(:delete, "https://picasaweb.google.com/data/entry/api/user/w.wnetrzak@gmail.com/albumid/123/photoid/456/commentid/987").to_return(:status => 200, :body => "")
64
+
65
+ result = Picasa::API::Comment.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret").destroy("987", :album_id => "123", :photo_id => "456")
66
+
67
+ assert_equal true, result
68
+ end
69
+ end
70
+ end
data/test/api/tag_test.rb CHANGED
@@ -42,4 +42,29 @@ describe Picasa::API::Tag do
42
42
  end
43
43
  end
44
44
  end
45
+
46
+ describe "#destroy" do
47
+ it "raises ArgumentError when no photo_id" do
48
+ tag = Picasa::API::Tag.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
49
+ assert_raises Picasa::ArgumentError, /photo_id/ do
50
+ tag.destroy("wtf", :album_id => "123")
51
+ end
52
+ end
53
+
54
+ it "raises ArgumentError when no album_id" do
55
+ tag = Picasa::API::Tag.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret")
56
+ assert_raises Picasa::ArgumentError, /album_id/ do
57
+ tag.destroy("wtf", :photo_id => "455")
58
+ end
59
+ end
60
+
61
+ it "gives true when success" do
62
+ stub_request(:post, "https://www.google.com/accounts/ClientLogin").to_return(fixture("auth/success.txt"))
63
+ stub_request(:delete, "https://picasaweb.google.com/data/entry/api/user/w.wnetrzak@gmail.com/albumid/123/photoid/456/tag/wtf").to_return(:status => 200, :body => "")
64
+
65
+ result = Picasa::API::Tag.new(:user_id => "w.wnetrzak@gmail.com", :password => "secret").destroy("wtf", :album_id => "123", :photo_id => "456")
66
+
67
+ assert_equal true, result
68
+ end
69
+ end
45
70
  end
@@ -0,0 +1,65 @@
1
+ HTTP/1.1 200 OK
2
+ Expires: Sun, 30 Sep 2012 09:09:17 GMT
3
+ Date: Sun, 30 Sep 2012 09:09:17 GMT
4
+ Cache-Control: private, max-age=0, must-revalidate, no-transform
5
+ Set-Cookie: _rtok=ZS2AJZMN4GwZ; Path=/; Secure; HttpOnly
6
+ Set-Cookie: S=photos_html=wWH1eSR_XDZiIU9n_ezhUQ; Domain=.google.com; Path=/; Secure; HttpOnly
7
+ Content-Type: application/atom+xml; charset=UTF-8; type=feed
8
+ Vary: Accept, X-GData-Authorization, GData-Version, Cookie
9
+ GData-Version: 2.0
10
+ ETag: W/"D0ADRncyeip7ImA9WhJbGUQ."
11
+ Last-Modified: Sun, 30 Sep 2012 09:02:57 GMT
12
+ X-Content-Type-Options: nosniff
13
+ X-Frame-Options: SAMEORIGIN
14
+ X-XSS-Protection: 1; mode=block
15
+ Server: GSE
16
+ Transfer-Encoding: chunked
17
+
18
+ <?xml version='1.0' encoding='UTF-8'?>
19
+ <feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:gphoto='http://schemas.google.com/photos/2007' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/&quot;D0ADRncyeip7ImA9WhJbGUQ.&quot;'>
20
+ <id>https://picasaweb.google.com/data/feed/user/106136347770555028022</id>
21
+ <updated>2012-09-30T09:02:57.992Z</updated>
22
+ <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#user'/>
23
+ <title>106136347770555028022</title>
24
+ <subtitle/>
25
+ <icon>https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s64-c/106136347770555028022.jpg</icon>
26
+ <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://picasaweb.google.com/data/feed/api/user/106136347770555028022'/>
27
+ <link rel='alternate' type='text/html' href='https://picasaweb.google.com/106136347770555028022'/>
28
+ <link rel='http://schemas.google.com/photos/2007#slideshow' type='application/x-shockwave-flash' href='https://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&amp;RGB=0x000000&amp;feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F106136347770555028022%3Falt%3Drss'/>
29
+ <link rel='self' type='application/atom+xml' href='https://picasaweb.google.com/data/feed/api/user/106136347770555028022?start-index=1&amp;max-results=100&amp;kind=comment'/>
30
+ <author>
31
+ <name>Wojciech Wnętrzak</name>
32
+ <uri>https://picasaweb.google.com/106136347770555028022</uri>
33
+ </author>
34
+ <generator version='1.00' uri='http://picasaweb.google.com/'>Picasaweb</generator>
35
+ <openSearch:totalResults>1</openSearch:totalResults>
36
+ <openSearch:startIndex>1</openSearch:startIndex>
37
+ <openSearch:itemsPerPage>100</openSearch:itemsPerPage>
38
+ <gphoto:user>106136347770555028022</gphoto:user>
39
+ <gphoto:nickname>Wojciech Wnętrzak</gphoto:nickname>
40
+ <gphoto:thumbnail>https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s64-c/106136347770555028022.jpg</gphoto:thumbnail>
41
+ <gphoto:quotalimit>1073741824</gphoto:quotalimit>
42
+ <gphoto:quotacurrent>758213</gphoto:quotacurrent>
43
+ <gphoto:maxPhotosPerAlbum>1000</gphoto:maxPhotosPerAlbum>
44
+ <entry gd:etag='W/&quot;D0ADRn04fCp7ImA9WhJbGUQ.&quot;'>
45
+ <id>https://picasaweb.google.com/data/entry/user/106136347770555028022/albumid/5793892606777564353/photoid/5793892628357238194/commentid/z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000</id>
46
+ <published>2012-09-30T09:02:57.334Z</published>
47
+ <updated>2012-09-30T09:02:57.334Z</updated>
48
+ <app:edited>2012-09-30T09:02:57.334Z</app:edited>
49
+ <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#comment'/>
50
+ <title>Wojciech Wnętrzak</title>
51
+ <content type='html'>testing comment</content>
52
+ <link rel='alternate' type='text/html' href='https://picasaweb.google.com/lh/photo/sPdyu2Pl7tE-Je04UbLSuiUdvMQllM3aC4Soztgbiog'/>
53
+ <link rel='self' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5793892606777564353/photoid/5793892628357238194/commentid/z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000?authkey=Gv1sRgCNmigd3KrbOHLA'/>
54
+ <link rel='edit' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5793892606777564353/photoid/5793892628357238194/commentid/z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000?authkey=Gv1sRgCNmigd3KrbOHLA'/>
55
+ <author>
56
+ <name>Wojciech Wnętrzak</name>
57
+ <uri>https://picasaweb.google.com/106136347770555028022</uri>
58
+ <gphoto:nickname>Wojciech Wnętrzak</gphoto:nickname>
59
+ <gphoto:thumbnail>https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s48-c/106136347770555028022.jpg</gphoto:thumbnail>
60
+ <gphoto:user>106136347770555028022</gphoto:user>
61
+ </author>
62
+ <gphoto:id>z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000</gphoto:id>
63
+ <gphoto:photoid>5793892628357238194</gphoto:photoid>
64
+ </entry>
65
+ </feed>
@@ -0,0 +1,48 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <feed xmlns='http://www.w3.org/2005/Atom' xmlns:app='http://www.w3.org/2007/app' xmlns:gphoto='http://schemas.google.com/photos/2007' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/&quot;D0ADRncyeip7ImA9WhJbGUQ.&quot;'>
3
+ <id>https://picasaweb.google.com/data/feed/user/106136347770555028022</id>
4
+ <updated>2012-09-30T09:02:57.992Z</updated>
5
+ <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#user'/>
6
+ <title>106136347770555028022</title>
7
+ <subtitle/>
8
+ <icon>https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s64-c/106136347770555028022.jpg</icon>
9
+ <link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://picasaweb.google.com/data/feed/api/user/106136347770555028022'/>
10
+ <link rel='alternate' type='text/html' href='https://picasaweb.google.com/106136347770555028022'/>
11
+ <link rel='http://schemas.google.com/photos/2007#slideshow' type='application/x-shockwave-flash' href='https://picasaweb.google.com/s/c/bin/slideshow.swf?host=picasaweb.google.com&amp;RGB=0x000000&amp;feed=https%3A%2F%2Fpicasaweb.google.com%2Fdata%2Ffeed%2Fapi%2Fuser%2F106136347770555028022%3Falt%3Drss'/>
12
+ <link rel='self' type='application/atom+xml' href='https://picasaweb.google.com/data/feed/api/user/106136347770555028022?start-index=1&amp;max-results=100&amp;kind=comment'/>
13
+ <author>
14
+ <name>Wojciech Wnętrzak</name>
15
+ <uri>https://picasaweb.google.com/106136347770555028022</uri>
16
+ </author>
17
+ <generator version='1.00' uri='http://picasaweb.google.com/'>Picasaweb</generator>
18
+ <openSearch:totalResults>1</openSearch:totalResults>
19
+ <openSearch:startIndex>1</openSearch:startIndex>
20
+ <openSearch:itemsPerPage>100</openSearch:itemsPerPage>
21
+ <gphoto:user>106136347770555028022</gphoto:user>
22
+ <gphoto:nickname>Wojciech Wnętrzak</gphoto:nickname>
23
+ <gphoto:thumbnail>https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s64-c/106136347770555028022.jpg</gphoto:thumbnail>
24
+ <gphoto:quotalimit>1073741824</gphoto:quotalimit>
25
+ <gphoto:quotacurrent>758213</gphoto:quotacurrent>
26
+ <gphoto:maxPhotosPerAlbum>1000</gphoto:maxPhotosPerAlbum>
27
+ <entry gd:etag='W/&quot;D0ADRn04fCp7ImA9WhJbGUQ.&quot;'>
28
+ <id>https://picasaweb.google.com/data/entry/user/106136347770555028022/albumid/5793892606777564353/photoid/5793892628357238194/commentid/z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000</id>
29
+ <published>2012-09-30T09:02:57.334Z</published>
30
+ <updated>2012-09-30T09:02:57.334Z</updated>
31
+ <app:edited>2012-09-30T09:02:57.334Z</app:edited>
32
+ <category scheme='http://schemas.google.com/g/2005#kind' term='http://schemas.google.com/photos/2007#comment'/>
33
+ <title>Wojciech Wnętrzak</title>
34
+ <content type='html'>testing comment</content>
35
+ <link rel='alternate' type='text/html' href='https://picasaweb.google.com/lh/photo/sPdyu2Pl7tE-Je04UbLSuiUdvMQllM3aC4Soztgbiog'/>
36
+ <link rel='self' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5793892606777564353/photoid/5793892628357238194/commentid/z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000?authkey=Gv1sRgCNmigd3KrbOHLA'/>
37
+ <link rel='edit' type='application/atom+xml' href='https://picasaweb.google.com/data/entry/api/user/106136347770555028022/albumid/5793892606777564353/photoid/5793892628357238194/commentid/z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000?authkey=Gv1sRgCNmigd3KrbOHLA'/>
38
+ <author>
39
+ <name>Wojciech Wnętrzak</name>
40
+ <uri>https://picasaweb.google.com/106136347770555028022</uri>
41
+ <gphoto:nickname>Wojciech Wnętrzak</gphoto:nickname>
42
+ <gphoto:thumbnail>https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s48-c/106136347770555028022.jpg</gphoto:thumbnail>
43
+ <gphoto:user>106136347770555028022</gphoto:user>
44
+ </author>
45
+ <gphoto:id>z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000</gphoto:id>
46
+ <gphoto:photoid>5793892628357238194</gphoto:photoid>
47
+ </entry>
48
+ </feed>
@@ -0,0 +1,67 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "helper"
3
+
4
+ describe Picasa::Presenter::CommentList do
5
+ before do
6
+ body = MultiXml.parse(fixture("presenters/comment_list.xml"))
7
+ @comment_list = Picasa::Presenter::CommentList.new(body["feed"])
8
+ end
9
+
10
+ it "has author name" do
11
+ assert_equal "Wojciech Wnętrzak", @comment_list.author.name
12
+ end
13
+
14
+ it "has author uri" do
15
+ assert_equal "https://picasaweb.google.com/106136347770555028022", @comment_list.author.uri
16
+ end
17
+
18
+ it "has links" do
19
+ assert_equal 4, @comment_list.links.size
20
+ end
21
+
22
+ it "has title" do
23
+ assert_equal "106136347770555028022", @comment_list.title
24
+ end
25
+
26
+ it "has updated" do
27
+ assert_equal "2012-09-30T09:02:57+00:00", @comment_list.updated.to_s
28
+ end
29
+
30
+ it "has icon" do
31
+ expected = "https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s64-c/106136347770555028022.jpg"
32
+ assert_equal expected, @comment_list.icon
33
+ end
34
+
35
+ it "has generator" do
36
+ assert_equal "Picasaweb", @comment_list.generator
37
+ end
38
+
39
+ it "has total_results" do
40
+ assert_equal 1, @comment_list.total_results
41
+ end
42
+
43
+ it "has start_index" do
44
+ assert_equal 1, @comment_list.start_index
45
+ end
46
+
47
+ it "has items_per_page" do
48
+ assert_equal 100, @comment_list.items_per_page
49
+ end
50
+
51
+ it "has user" do
52
+ assert_equal "106136347770555028022", @comment_list.user
53
+ end
54
+
55
+ it "has nickname" do
56
+ assert_equal "Wojciech Wnętrzak", @comment_list.nickname
57
+ end
58
+
59
+ it "has thumbnail" do
60
+ expected = "https://lh3.googleusercontent.com/-6ezHc54U8x0/AAAAAAAAAAI/AAAAAAAAAAA/PBuxm7Ehn6E/s64-c/106136347770555028022.jpg"
61
+ assert_equal expected, @comment_list.thumbnail
62
+ end
63
+
64
+ it "has entries" do
65
+ assert_equal 1, @comment_list.entries.size
66
+ end
67
+ end
@@ -0,0 +1,56 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "helper"
3
+
4
+ describe Picasa::Presenter::Comment do
5
+ describe "comment from comment list" do
6
+ before do
7
+ body = MultiXml.parse(fixture("presenters/comment_list.xml"))
8
+ @comment = Picasa::Presenter::Comment.new(body["feed"]["entry"])
9
+ end
10
+
11
+ it "has author name" do
12
+ assert_equal "Wojciech Wnętrzak", @comment.author.name
13
+ end
14
+
15
+ it "has author uri" do
16
+ assert_equal "https://picasaweb.google.com/106136347770555028022", @comment.author.uri
17
+ end
18
+
19
+ it "has links" do
20
+ assert_equal 3, @comment.links.size
21
+ end
22
+
23
+ it "has published" do
24
+ assert_equal "2012-09-30T09:02:57+00:00", @comment.published.to_s
25
+ end
26
+
27
+ it "has updated" do
28
+ assert_equal "2012-09-30T09:02:57+00:00", @comment.updated.to_s
29
+ end
30
+
31
+ it "has edited" do
32
+ assert_equal "2012-09-30T09:02:57+00:00", @comment.edited.to_s
33
+ end
34
+
35
+ it "has etag" do
36
+ assert_equal "W/\"D0ADRn04fCp7ImA9WhJbGUQ.\"", @comment.etag
37
+ end
38
+
39
+ it "has title" do
40
+ assert_equal "Wojciech Wnętrzak", @comment.title
41
+ end
42
+
43
+ it "has content" do
44
+ assert_equal "testing comment", @comment.content
45
+ end
46
+
47
+ it "has id" do
48
+ expected = "z13stn0rtrvkvpnbm04cgjbgjkmwyr5ot4g-1348995777334000"
49
+ assert_equal expected, @comment.id
50
+ end
51
+
52
+ it "has photo_id" do
53
+ assert_equal "5793892628357238194", @comment.photo_id
54
+ end
55
+ end
56
+ 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.5.2
4
+ version: 0.5.3
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-09-16 00:00:00.000000000 Z
12
+ date: 2012-09-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_xml
@@ -72,16 +72,19 @@ files:
72
72
  - LICENSE
73
73
  - README.md
74
74
  - Rakefile
75
- - example/add_tags_to_photo.rb
76
- - example/create_new_album.rb
77
- - example/delete_all_photos.rb
78
- - example/get_some_albums.rb
79
- - example/get_some_photos.rb
80
- - example/upload_photo.rb
75
+ - examples/add_tags_to_photo.rb
76
+ - examples/create_new_album.rb
77
+ - examples/delete_all_photos.rb
78
+ - examples/download_all_albums.rb
79
+ - examples/download_one_album.rb
80
+ - examples/get_some_albums.rb
81
+ - examples/get_some_photos.rb
82
+ - examples/upload_photo.rb
81
83
  - extra/Thorfile
82
84
  - lib/picasa.rb
83
85
  - lib/picasa/api/album.rb
84
86
  - lib/picasa/api/base.rb
87
+ - lib/picasa/api/comment.rb
85
88
  - lib/picasa/api/photo.rb
86
89
  - lib/picasa/api/tag.rb
87
90
  - lib/picasa/client.rb
@@ -92,6 +95,8 @@ files:
92
95
  - lib/picasa/presenter/album_list.rb
93
96
  - lib/picasa/presenter/author.rb
94
97
  - lib/picasa/presenter/base.rb
98
+ - lib/picasa/presenter/comment.rb
99
+ - lib/picasa/presenter/comment_list.rb
95
100
  - lib/picasa/presenter/content.rb
96
101
  - lib/picasa/presenter/link.rb
97
102
  - lib/picasa/presenter/media.rb
@@ -101,12 +106,14 @@ files:
101
106
  - lib/picasa/presenter/thumbnail.rb
102
107
  - lib/picasa/template.rb
103
108
  - lib/picasa/templates/new_album.xml.erb
109
+ - lib/picasa/templates/new_comment.xml.erb
104
110
  - lib/picasa/templates/new_photo.xml.erb
105
111
  - lib/picasa/templates/new_tag.xml.erb
106
112
  - lib/picasa/utils.rb
107
113
  - lib/picasa/version.rb
108
114
  - picasa.gemspec
109
115
  - test/api/album_test.rb
116
+ - test/api/comment_test.rb
110
117
  - test/api/photo_test.rb
111
118
  - test/api/tag_test.rb
112
119
  - test/client_test.rb
@@ -120,6 +127,7 @@ files:
120
127
  - test/fixtures/album/album-show-with-tag-and-one-photo.txt
121
128
  - test/fixtures/album/album-show.txt
122
129
  - test/fixtures/auth/success.txt
130
+ - test/fixtures/comment/comment-list.txt
123
131
  - test/fixtures/exceptions/forbidden.txt
124
132
  - test/fixtures/exceptions/not_found.txt
125
133
  - test/fixtures/exceptions/precondition_failed.txt
@@ -132,6 +140,7 @@ files:
132
140
  - test/fixtures/presenters/album_list.xml
133
141
  - test/fixtures/presenters/album_show.xml
134
142
  - test/fixtures/presenters/album_show_with_one_photo.xml
143
+ - test/fixtures/presenters/comment_list.xml
135
144
  - test/fixtures/presenters/tag_list.xml
136
145
  - test/fixtures/tag/tag-list.txt
137
146
  - test/helper.rb
@@ -139,6 +148,8 @@ files:
139
148
  - test/presenter/album_test.rb
140
149
  - test/presenter/author_test.rb
141
150
  - test/presenter/base_test.rb
151
+ - test/presenter/comment_list_test.rb
152
+ - test/presenter/comment_test.rb
142
153
  - test/presenter/content_test.rb
143
154
  - test/presenter/link_test.rb
144
155
  - test/presenter/media_test.rb