picasaweb-backup 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65b528a9faea826628aa1501f2eb4fecd1a4859b
4
+ data.tar.gz: 5cdbe52dd1e524d088415b036ad20e38886f47ba
5
+ SHA512:
6
+ metadata.gz: 7b8acd1ddb8fe26302564dfdb8ff1fd269bc693ba238e9caf366e593498587e30b8f50e9d4fe90f39db79a807c75f412ec1f8018c78a4d2616d02c62ee37f5c5
7
+ data.tar.gz: 15365bbb6f58c8c2b98cb5416e0df10d01ac69f014a4c4057846724018da538b3ed7cafe5733d1f6da93e22afdbd6f53c5febf1fe6072bbae5a74e12bbd4cb84
data/.gitignore CHANGED
@@ -15,3 +15,7 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+
19
+ tokens.yaml
20
+ client_id.json
21
+ Albums
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
- gem "gdata_19", "~> 1.1.5"
3
- gem "artii", "~> 2.0.1"
4
- gem "colored", "~> 1.2"
2
+ gem 'artii', '~> 2.1', '>= 2.1.1'
3
+ gem 'colored', '~> 1.2'
4
+ gem 'googleauth', '~> 0.5.1'
5
+ gem 'http'
@@ -29,15 +29,23 @@ opt_parser = OptionParser.new('Backing up your Picasaweb photos') do |opt|
29
29
  end
30
30
 
31
31
  opt_parser.parse!(ARGV)
32
- cli = Picasaweb::CLI.new opts
33
32
 
34
- begin
33
+ if !File.exists?("client_id.json")
34
+ puts("No file client_id.json found. \n" \
35
+ "Please go to https://console.developers.google.com/apis/credentials "\
36
+ "to generate an OAuth CLI app and download, client_id.json file and "\
37
+ "place it in the directory where you run picasaweb-backup.")
35
38
 
36
- cli.start_backup
39
+ else
37
40
 
38
- rescue => e
39
- cli.print "ERROR: #{e.message}".red
40
- cli.print ""
41
- cli.print opt_parser
42
- end
41
+ begin
42
+
43
+ cli = Picasaweb::CLI.new opts
44
+ cli.start_backup
43
45
 
46
+ rescue => e
47
+ puts "ERROR: #{e.message}".red
48
+ puts e.backtrace
49
+ end
50
+
51
+ end
@@ -8,9 +8,11 @@
8
8
 
9
9
  require "version"
10
10
  require "yaml"
11
- require "rubygems"
12
- require "gdata"
13
11
  require "logger"
12
+ require 'googleauth'
13
+ require 'googleauth/stores/file_token_store'
14
+ require 'http'
15
+ require 'nokogiri'
14
16
 
15
17
  #monkey-patch logger formatting
16
18
  class Logger
@@ -20,24 +22,93 @@ class Logger
20
22
  end
21
23
 
22
24
  module Picasaweb
25
+ class Client
26
+
27
+ OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'
28
+
29
+ def initialize
30
+ scope = 'https://picasaweb.google.com/data/'
31
+ client_id = Google::Auth::ClientId.from_file('client_id.json')
32
+ token_store = Google::Auth::Stores::FileTokenStore.new(:file => 'tokens.yaml')
33
+ authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)
34
+
35
+ user_id = "picasaweb-backup"
36
+
37
+ credentials = authorizer.get_credentials(user_id)
38
+
39
+ if credentials.nil?
40
+ url = authorizer.get_authorization_url(base_url: OOB_URI )
41
+ puts "Open #{url} in your browser and enter the resulting code:"
42
+ code = gets
43
+ @credentials = authorizer.get_and_store_credentials_from_code(
44
+ user_id: user_id, code: code, base_url: OOB_URI)
45
+ else
46
+ puts "Found token #{credentials.access_token}. Refreshing..."
47
+ credentials.fetch_access_token!
48
+ @credentials = credentials
49
+ end
50
+ end
51
+
52
+ # Retrieves all albums for a user.
53
+ def get_albums
54
+ uri = "https://picasaweb.google.com/data/feed/api/user/default"
55
+ feed = get(uri)
56
+ entries = feed.css("entry")
57
+
58
+ entries.map do |entry|
59
+ { :id => entry.css('gphoto|id').text,
60
+ :user => entry.css('gphoto|user').text,
61
+ :title => entry.css('title').text }
62
+ end
63
+ end
64
+
65
+ # Retrieves all photos from an album.
66
+ def get_photos(album)
67
+ uri = "https://picasaweb.google.com/data/feed/api/user/" +
68
+ "default/albumid/#{album[:id]}?kind=photo&imgmax=d"
69
+
70
+ entries = get(uri).css("entry")
71
+
72
+ entries.map do |entry|
73
+ url = entry.css('media|group > media|content[url]').first.attribute("url").value
74
+ photo = { :id => entry.css('gphoto|id').text,
75
+ :album_id => entry.css('gphoto|albumid').text,
76
+ :title => entry.css('title').text,
77
+ :url => url
78
+ }
79
+ end
80
+ end
81
+
82
+
83
+ def get(url)
84
+ res = HTTP[:authorization => "Bearer #{@credentials.access_token}"].get(url)
85
+ Nokogiri::XML(res.body)
86
+ end
87
+
88
+ def download(photo)
89
+ response = HTTP.get(photo[:url])
90
+ File.open(photo[:title], 'w') { |f| f.write response.body }
91
+ end
92
+
93
+ end
94
+
23
95
  class CLI
96
+
24
97
  ALBUM_DIR = "Albums"
98
+
25
99
  def initialize opts
26
100
  @opts = opts
101
+ @client = Client.new
27
102
 
28
103
  if opts[:dir]
29
104
  Dir.chdir opts[:dir]
105
+ self.print "Changing working directory to #{opts[:dir]}"
30
106
  end
31
107
 
32
108
  if @opts[:log]
33
109
  @logger = Logger.new "picasaweb-backup.log", shift_age = "monthly"
34
110
  end
35
111
 
36
- if opts[:dir]
37
- self.print "Changing working directory to #{opts[:dir]}"
38
- end
39
-
40
- @account = File.open("account.yml", 'r') { |f| YAML.load f }
41
112
  end
42
113
 
43
114
  def print msg
@@ -48,67 +119,26 @@ module Picasaweb
48
119
  end
49
120
  end
50
121
 
51
- def verify_account account
52
- if account["username"].nil?
53
- raise "Please add your username to account.yml"
54
- elsif account["password"].nil?
55
- raise "Please add your password to account.yml"
56
- end
57
- end
58
-
59
- def picasa_client(username, password)
60
- client = GData::Client::Photos.new
61
- client.clientlogin(username, password)
62
- client
63
- end
64
-
65
- def ensure_exists dir
122
+ def ensure_exists(dir)
66
123
  if !File.directory? dir
67
124
  Dir.mkdir dir
68
125
  self.print "Creating directory '#{dir}'"
69
126
  end
70
127
  end
71
128
 
72
- # Retrieves all albums for a user.
73
- def get_albums(client, user = nil)
74
- uri = "http://picasaweb.google.com/data/feed/api/user/#{user || 'default'}"
75
- feed = client.get(uri).to_xml
76
- albums = []
77
- feed.elements.each('entry') do |entry|
78
- next unless entry.elements['gphoto:id']
79
- albums << { :id => entry.elements['gphoto:id'].text,
80
- :user => entry.elements['gphoto:user'].text,
81
- :title => entry.elements['title'].text }
82
- end
83
- albums
84
- end
85
-
86
- def download_album client, album
129
+ def download_album(client, album)
87
130
  Dir.chdir album[:title] do
88
131
  self.print "Checking for new photos in '#{album[:title]}'"
89
132
  photos = nil
90
133
  until photos
91
- begin
92
- photos = get_photos client, album
93
- rescue GData::Client::ServerError
94
- "Server error, retrying\n"
95
- end
134
+ photos = client.get_photos(album)
96
135
  end
97
136
 
98
137
  downloaded_photos = 0
99
138
  photos.each do |photo|
100
139
  if !File.exists? photo[:title]
101
140
  self.print " ==> #{photo[:title]}"
102
- response = nil
103
- until response
104
- begin
105
- response = client.get photo[:url]
106
- rescue GData::Client::ServerError
107
- "Server error, retrying\n"
108
- end
109
- end
110
-
111
- File.open(photo[:title], 'w') { |f| f.write response.body }
141
+ client.download(photo)
112
142
  downloaded_photos += 1
113
143
  end
114
144
  end
@@ -118,38 +148,17 @@ module Picasaweb
118
148
  end
119
149
  end
120
150
 
121
- # Retrieves all photos from an album.
122
- def get_photos(client, album)
123
- uri = "http://picasaweb.google.com/data/feed/api/user/" +
124
- "#{album[:user] || 'default'}/albumid/#{album[:id]}?kind=photo&imgmax=d"
125
-
126
- feed = client.get(uri).to_xml
127
- photos = []
128
- feed.elements.each('entry') do |entry|
129
- next unless entry.elements['gphoto:id']
130
- next unless entry.elements['media:group']
131
- photo = { :id => entry.elements['gphoto:id'].text,
132
- :album_id => entry.elements['gphoto:albumid'].text,
133
- :title => entry.elements['title'].text }
134
- entry.elements['media:group'].elements.each('media:content') do |content|
135
- photo[:url] = content.attribute('url').value
136
- end
137
- photos << photo
138
- end
139
- photos
140
- end
141
-
142
151
  def start_backup
143
- verify_account @account
144
- client = picasa_client @account["username"], @account["password"]
145
- albums = get_albums client
152
+ albums = @client.get_albums.select do |album|
153
+ album[:title].downcase != "auto backup"
154
+ end
146
155
 
147
- ensure_exists ALBUM_DIR
156
+ ensure_exists(ALBUM_DIR)
148
157
  Dir.chdir ALBUM_DIR
149
158
 
150
159
  albums.each do |album|
151
160
  ensure_exists album[:title]
152
- download_album client, album
161
+ download_album(@client, album)
153
162
  end
154
163
 
155
164
  end
@@ -1,5 +1,5 @@
1
1
  module Picasaweb
2
2
  module Backup
3
- VERSION = "0.4.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -3,16 +3,17 @@ require File.expand_path('../lib/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Leonard Ehrenfried"]
6
- gem.email = ['leonard.ehrenfried@web.de']
6
+ gem.email = ['leonard.ehrenfried@gmail.com']
7
7
  gem.summary = "Picasa Web Albums backup tool"
8
8
  gem.description = %{Backup all your photos from Google's Picasa Web Albums service,
9
9
  can be run repeatedly on the same folder and only downloads new files.}
10
10
 
11
- gem.homepage = 'http://github.com/lenniboy/picasaweb-backup'
11
+ gem.homepage = 'http://github.com/leonardehrenfried/picasaweb-backup'
12
12
 
13
- gem.add_dependency('gdata_19', '~> 1.1.5')
14
- gem.add_dependency('artii', '~> 2.0.1')
15
- gem.add_dependency('colored', '~> 1.2')
13
+ gem.add_dependency('artii', '~> 2.1')
14
+ gem.add_dependency('colored', '~> 1.2')
15
+ gem.add_dependency('googleauth', '~> 0.5.1')
16
+ gem.add_dependency('http', '~> 2.1')
16
17
 
17
18
  gem.files = `git ls-files`.split($\)
18
19
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
metadata CHANGED
@@ -1,74 +1,82 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picasaweb-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
5
- prerelease:
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Leonard Ehrenfried
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-08-08 00:00:00.000000000 Z
11
+ date: 2016-12-01 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- name: gdata_19
14
+ name: artii
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
- version: 1.1.5
19
+ version: '2.1'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
- version: 1.1.5
26
+ version: '2.1'
30
27
  - !ruby/object:Gem::Dependency
31
- name: artii
28
+ name: colored
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: 2.0.1
33
+ version: '1.2'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: 2.0.1
40
+ version: '1.2'
46
41
  - !ruby/object:Gem::Dependency
47
- name: colored
42
+ name: googleauth
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ~>
45
+ - - "~>"
52
46
  - !ruby/object:Gem::Version
53
- version: '1.2'
47
+ version: 0.5.1
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ~>
52
+ - - "~>"
60
53
  - !ruby/object:Gem::Version
61
- version: '1.2'
62
- description: ! "Backup all your photos from Google's Picasa Web Albums service,\n
63
- \ can be run repeatedly on the same folder and only downloads new files."
54
+ version: 0.5.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: http
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.1'
69
+ description: |-
70
+ Backup all your photos from Google's Picasa Web Albums service,
71
+ can be run repeatedly on the same folder and only downloads new files.
64
72
  email:
65
- - leonard.ehrenfried@web.de
73
+ - leonard.ehrenfried@gmail.com
66
74
  executables:
67
75
  - picasaweb-backup
68
76
  extensions: []
69
77
  extra_rdoc_files: []
70
78
  files:
71
- - .gitignore
79
+ - ".gitignore"
72
80
  - Gemfile
73
81
  - Gemfile.lock
74
82
  - LICENSE
@@ -78,28 +86,27 @@ files:
78
86
  - lib/picasaweb-backup.rb
79
87
  - lib/version.rb
80
88
  - picasaweb-backup.gemspec
81
- homepage: http://github.com/lenniboy/picasaweb-backup
89
+ homepage: http://github.com/leonardehrenfried/picasaweb-backup
82
90
  licenses: []
91
+ metadata: {}
83
92
  post_install_message:
84
93
  rdoc_options: []
85
94
  require_paths:
86
95
  - lib
87
96
  required_ruby_version: !ruby/object:Gem::Requirement
88
- none: false
89
97
  requirements:
90
- - - ! '>='
98
+ - - ">="
91
99
  - !ruby/object:Gem::Version
92
100
  version: '0'
93
101
  required_rubygems_version: !ruby/object:Gem::Requirement
94
- none: false
95
102
  requirements:
96
- - - ! '>='
103
+ - - ">="
97
104
  - !ruby/object:Gem::Version
98
105
  version: '0'
99
106
  requirements: []
100
107
  rubyforge_project:
101
- rubygems_version: 1.8.24
108
+ rubygems_version: 2.4.5
102
109
  signing_key:
103
- specification_version: 3
110
+ specification_version: 4
104
111
  summary: Picasa Web Albums backup tool
105
112
  test_files: []