photo-helper 0.3.1 → 0.4
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.
- 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
|