photo-helper 0.3.1 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/helpers/smugmug_album.rb +89 -24
- data/lib/helpers/smugmug_api.rb +7 -7
- data/lib/photo-helper/smugmug.rb +19 -13
- data/lib/photo-helper/version.rb +1 -1
- data/photo-helper.gemspec +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80cbb16dcdcf8f7cbadcf310bd1cb9817783660e
|
4
|
+
data.tar.gz: 1b343c9d6eed2fa4b8a0c228b17724c0f9214343
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 779dd813a904a2e01ba4b452f1c772b47ff0b551befcdf89592bea2fa92adbbfadc3833b2943f6a076da023baee960443e336df7402b4373e1c85ca87a90c8d5
|
7
|
+
data.tar.gz: 877c46eadf49655521a78bf16e993ebf067f465d3298bdc397572a87e8a1631ddad1a9aff638e95bc62a35b876ba481165f69d52ace8867a1f5476d5b8216b81
|
data/Gemfile.lock
CHANGED
@@ -7,12 +7,36 @@ require 'set'
|
|
7
7
|
class SmugmugAlbumHelper
|
8
8
|
attr_accessor :smugmug_api
|
9
9
|
|
10
|
-
# to figure out what to delete, read all xmp files, loop through uploaded files and check xmp file
|
11
|
-
|
12
10
|
PATH_REGEX = %r{^.+Pictures\/.+\/(\d{4})\/(\d{2})_.+\/[^_]+_([^\/]+)}
|
13
|
-
KEYWORD_WHITELITS = %w(
|
11
|
+
KEYWORD_WHITELITS = %w(instagram exported)
|
12
|
+
|
13
|
+
def self.supported_folder?(search_path)
|
14
|
+
PATH_REGEX.match?(search_path)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.recursive_sync(search_path)
|
18
|
+
folders = Dir[File.join(search_path, "*/")]
|
19
|
+
folders.each do |folder|
|
20
|
+
if SmugmugAlbumHelper.supported_folder?(folder)
|
21
|
+
puts "Syncing #{folder}\n"
|
22
|
+
sync(folder)
|
23
|
+
puts "\n"
|
24
|
+
else
|
25
|
+
recursive_sync(folder)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.sync(search_path)
|
31
|
+
smugmug = SmugmugAlbumHelper.new(search_path)
|
32
|
+
smugmug.upload_dl
|
33
|
+
puts "\n"
|
34
|
+
smugmug.collect_select
|
35
|
+
end
|
14
36
|
|
15
37
|
def initialize(search_path, album = nil)
|
38
|
+
@search_extensions = IMAGE_EXTENSIONS.concat(["XMP"])
|
39
|
+
|
16
40
|
@search_path = Pathname.new(search_path)
|
17
41
|
@smugmug = SmugmugAPI.new
|
18
42
|
|
@@ -45,19 +69,19 @@ class SmugmugAlbumHelper
|
|
45
69
|
end
|
46
70
|
|
47
71
|
def image_list
|
48
|
-
Dir[
|
72
|
+
Dir[File.join(@search_path, "/**/*.{#{@search_extensions.join(',')}}")].reject { |p| FileHelper.ingore_file?(p)}
|
49
73
|
end
|
50
74
|
|
51
75
|
def exported_list
|
52
|
-
Dir[
|
76
|
+
Dir[File.join(@search_path, "/**/{Exported,exported}/*.*")]
|
53
77
|
end
|
54
78
|
|
55
79
|
def instagram_list
|
56
|
-
Dir[
|
80
|
+
Dir[File.join(@search_path, "/**/{Instagram,instagram}/*.*")]
|
57
81
|
end
|
58
82
|
|
59
83
|
def merge_exported(images = image_list, concat = false)
|
60
|
-
exported = Dir["#{@search_path}/**/{Exported,exported}
|
84
|
+
exported = Dir["#{@search_path}/**/{Exported,exported}/*.*"]
|
61
85
|
unless concat
|
62
86
|
exported_basenames = exported.map { |p| File.basename(p, ".*") }
|
63
87
|
images = images.reject { |p| exported_basenames.include? File.basename(p, ".*") }
|
@@ -79,16 +103,17 @@ class SmugmugAlbumHelper
|
|
79
103
|
image_list_hash = {}
|
80
104
|
images.each do |i|
|
81
105
|
filename = File.basename(i, ".*")
|
82
|
-
|
83
|
-
@keyword_list.merge(
|
106
|
+
keywords = image_dir_keywords(i)
|
107
|
+
@keyword_list.merge(keywords) if keywords
|
108
|
+
|
84
109
|
push_hash_array(image_list_hash, filename, file: i,
|
85
|
-
keywords:
|
110
|
+
keywords: keywords,
|
86
111
|
md5: Digest::MD5.file(i).hexdigest)
|
87
112
|
end
|
88
113
|
image_list_hash
|
89
114
|
end
|
90
115
|
|
91
|
-
def sync(album, image_list_hash, reject_trash = true)
|
116
|
+
def sync(album, image_list_hash, reject_trash = true, delete: true)
|
92
117
|
uploaded_hash = uploaded_to_hash(album)
|
93
118
|
|
94
119
|
to_upload = {}
|
@@ -127,7 +152,11 @@ class SmugmugAlbumHelper
|
|
127
152
|
image_hash = image_list_hash[filename].find do |image|
|
128
153
|
uploaded_match_requested?(image, uploaded)
|
129
154
|
end
|
130
|
-
|
155
|
+
|
156
|
+
if image_hash.nil?
|
157
|
+
to_delete.push(uploaded)
|
158
|
+
next
|
159
|
+
end
|
131
160
|
to_delete.push(uploaded) if reject_trash && ImageHelper.color_class(image_hash[:file]) == "Trash"
|
132
161
|
else
|
133
162
|
to_delete.push(uploaded)
|
@@ -140,18 +169,19 @@ class SmugmugAlbumHelper
|
|
140
169
|
upload(album, images, keywords)
|
141
170
|
end
|
142
171
|
|
143
|
-
|
172
|
+
to_update.each do |keywords, images|
|
173
|
+
puts keywords
|
174
|
+
update(album, images, keywords)
|
175
|
+
end
|
176
|
+
# puts "delete #{to_delete.count}???"
|
177
|
+
|
178
|
+
if delete && to_delete.any?
|
144
179
|
puts "Deleting #{to_delete.count} images"
|
145
180
|
to_delete.each do |uploaded|
|
146
181
|
puts uploaded[:filename]
|
147
182
|
@smugmug.http(:delete, uploaded[:uri])
|
148
183
|
end
|
149
184
|
end
|
150
|
-
|
151
|
-
to_update.each do |keywords, images|
|
152
|
-
puts keywords
|
153
|
-
update(album, images, keywords)
|
154
|
-
end
|
155
185
|
end
|
156
186
|
|
157
187
|
def upload(album, pictures, keywords = nil)
|
@@ -172,15 +202,50 @@ class SmugmugAlbumHelper
|
|
172
202
|
@smugmug.update_images(pictures, album[:id], headers, workers: 8, filename_as_title: true)
|
173
203
|
end
|
174
204
|
|
175
|
-
def upload_dl
|
205
|
+
def upload_dl(album_name = nil)
|
206
|
+
album = if album
|
207
|
+
@smugmug.get_or_create_album(album_name)
|
208
|
+
else
|
209
|
+
@dl_album
|
210
|
+
end
|
211
|
+
|
176
212
|
@keyword_list = Set.new
|
177
|
-
puts "Uploading all images to album #{@album_name} --> #{
|
213
|
+
puts "Uploading all images to album #{album_name || @album_name} --> #{album[:web_uri]}\n"
|
178
214
|
|
179
215
|
@image_list = image_list_to_hash(image_list)
|
180
216
|
@image_list = merge_hash_array(@image_list, image_list_to_hash(exported_list))
|
181
217
|
@image_list = merge_hash_array(@image_list, image_list_to_hash(instagram_list))
|
218
|
+
sync(album, @image_list, true)
|
219
|
+
end
|
220
|
+
|
221
|
+
def collect_select
|
222
|
+
@keyword_list = Set.new
|
223
|
+
|
224
|
+
pictures = image_list
|
225
|
+
pictures = pictures.select { |p| ImageHelper.is_select?(p) }
|
226
|
+
pictures = merge_exported(pictures)
|
182
227
|
|
183
|
-
|
228
|
+
puts "Collecting selects to album #{@album_name} --> #{@album[:web_uri]}\n"
|
229
|
+
|
230
|
+
@image_list = image_list_to_hash(pictures)
|
231
|
+
@uploaded_hash ||= uploaded_to_hash(@album)
|
232
|
+
@dl_uploaded_hash ||= uploaded_to_hash(@dl_album)
|
233
|
+
|
234
|
+
to_collect = []
|
235
|
+
# no_match = {}
|
236
|
+
|
237
|
+
@image_list.each do |filename, images|
|
238
|
+
images.each do |image|
|
239
|
+
next unless @dl_uploaded_hash.key?(filename)
|
240
|
+
@dl_uploaded_hash[filename].each do |uploaded|
|
241
|
+
next unless uploaded_match_requested?(image, uploaded)
|
242
|
+
to_collect.push(uploaded[:uri]) unless to_collect.include? uploaded[:uri]
|
243
|
+
break
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
@smugmug.collect_images(to_collect, @album[:id])
|
184
249
|
end
|
185
250
|
|
186
251
|
def upload_select
|
@@ -214,7 +279,7 @@ class SmugmugAlbumHelper
|
|
214
279
|
end
|
215
280
|
|
216
281
|
def image_dir_keywords(image)
|
217
|
-
rel = Pathname.new(image).relative_path_from(@search_path).to_s.split("/")
|
282
|
+
rel = Pathname.new(image).relative_path_from(@search_path).to_s.downcase.split("/")
|
218
283
|
# ignore first and last parts
|
219
284
|
rel &= KEYWORD_WHITELITS
|
220
285
|
return nil if rel.empty?
|
@@ -225,8 +290,8 @@ class SmugmugAlbumHelper
|
|
225
290
|
if image[:keywords].nil?
|
226
291
|
# empty from keyword list
|
227
292
|
return true if uploaded[:keywords].nil? || @keyword_list & uploaded[:keywords] == Set.new
|
228
|
-
|
229
|
-
return true
|
293
|
+
elsif image[:keywords] - uploaded[:keywords] == []
|
294
|
+
return true
|
230
295
|
end
|
231
296
|
false
|
232
297
|
end
|
data/lib/helpers/smugmug_api.rb
CHANGED
@@ -177,7 +177,7 @@ class SmugmugAPI
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def post(url, body = {}, headers = {})
|
180
|
-
url.tr
|
180
|
+
url = url.tr(' ', '-')
|
181
181
|
headers['Accept'] = 'application/json'
|
182
182
|
response = @http.post(url, body, headers)
|
183
183
|
raise "Request failed\n#{response.body}" unless response.is_a? Net::HTTPSuccess
|
@@ -203,27 +203,27 @@ class SmugmugAPI
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def upload_images(images, album_id, headers = {}, workers: 4, filename_as_title: false)
|
206
|
-
counter = 0
|
207
206
|
Parallel.each(images, in_processes: workers, progress: "Uploading images") do |image|
|
208
207
|
upload(image, album_id, headers, filename_as_title: filename_as_title)
|
209
|
-
# puts "#{counter}/#{images.count / workers}
|
210
208
|
puts "Done #{image}"
|
211
209
|
end
|
212
210
|
end
|
213
211
|
|
214
212
|
def update_images(images, album_id, headers = {}, workers: 4, filename_as_title: false)
|
215
|
-
counter = 0
|
216
|
-
|
217
213
|
Parallel.each(images, in_processes: workers, progress: "Updating images") do |image|
|
218
214
|
# replace not working, delete then upload
|
219
215
|
http(:delete, image[:uri])
|
220
216
|
upload(image[:file], album_id, headers, filename_as_title: filename_as_title)
|
221
|
-
# counter += 1
|
222
|
-
# puts "#{counter}/#{images.count / workers}
|
223
217
|
puts "Done #{image[:file]}"
|
224
218
|
end
|
225
219
|
end
|
226
220
|
|
221
|
+
def collect_images(images, album_id)
|
222
|
+
return if images.empty?
|
223
|
+
images = images.join(",") if images.is_a? Array
|
224
|
+
post("/api/v2/album/#{album_id}!collectimages", "CollectUris" => images)
|
225
|
+
end
|
226
|
+
|
227
227
|
def request_access_token
|
228
228
|
@consumer = OAuth::Consumer.new(@secrets.api_key, @secrets.api_secret,
|
229
229
|
site: OAUTH_ORIGIN,
|
data/lib/photo-helper/smugmug.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'helpers/smugmug_album'
|
3
4
|
require 'date'
|
4
5
|
require 'helpers/image_helper'
|
@@ -12,35 +13,40 @@ module PhotoHelper
|
|
12
13
|
method_option :folder, aliases: '-f', type: :string, default: '.'
|
13
14
|
method_option :recursive, aliases: '-r', type: :boolean, default: false
|
14
15
|
method_option :dry_run, aliases: '-d', type: :boolean, default: false
|
15
|
-
|
16
|
+
method_option :no_delete, type: :boolean, default: false
|
17
|
+
def sync(folder = nil, album_name = nil)
|
16
18
|
search_path = File.expand_path(folder)
|
17
19
|
|
18
|
-
|
20
|
+
if options[:recursive]
|
21
|
+
SmugmugAlbumHelper.recursive_sync(search_path)
|
22
|
+
|
23
|
+
return
|
24
|
+
end
|
19
25
|
|
20
|
-
@smugmug.upload_select
|
21
26
|
puts("\n")
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
+
if album_name
|
28
|
+
@smugmug = SmugmugAlbumHelper.new(search_path)
|
29
|
+
@smugmug.upload_dl(album_name)
|
30
|
+
else
|
31
|
+
SmugmugAlbumHelper.sync(search_path)
|
32
|
+
end
|
27
33
|
end
|
28
34
|
|
29
|
-
desc 'oauth',
|
35
|
+
desc 'oauth', 'fetch oauth credentials'
|
30
36
|
def oauth
|
31
37
|
SmugmugAPI.new.request_access_token
|
32
38
|
end
|
33
39
|
|
34
|
-
desc 'albums',
|
40
|
+
desc 'albums', 'list albums with their weburl'
|
35
41
|
def albums
|
36
42
|
@smugmug = SmugmugAPI.new
|
37
43
|
albums = @smugmug.albums_long
|
38
44
|
|
39
|
-
current_month = albums.first[:path].split(
|
40
|
-
output = [
|
45
|
+
current_month = albums.first[:path].split('/')[1]
|
46
|
+
output = ['# Photos', "## #{current_month}"]
|
41
47
|
|
42
48
|
albums.each do |a|
|
43
|
-
month = a[:path].split(
|
49
|
+
month = a[:path].split('/')[1]
|
44
50
|
next unless month
|
45
51
|
if month != current_month
|
46
52
|
current_month = month
|
data/lib/photo-helper/version.rb
CHANGED
data/photo-helper.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: photo-helper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: '0.4'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Caldwell
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|