picasa 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
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