flickarr 0.1.0
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 +7 -0
- data/.rubocop_todo.yml +13 -0
- data/CHANGELOG.md +42 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/HELP.txt +50 -0
- data/HOWTO.md +260 -0
- data/LICENSE.txt +21 -0
- data/README.md +109 -0
- data/Rakefile +10 -0
- data/TODO.md +6 -0
- data/exe/flickarr +5 -0
- data/lib/flickarr/auth.rb +43 -0
- data/lib/flickarr/cli.rb +692 -0
- data/lib/flickarr/client/photo_query.rb +23 -0
- data/lib/flickarr/client/profile_query.rb +19 -0
- data/lib/flickarr/client.rb +94 -0
- data/lib/flickarr/collection.rb +103 -0
- data/lib/flickarr/config.rb +88 -0
- data/lib/flickarr/errors.rb +7 -0
- data/lib/flickarr/license.rb +34 -0
- data/lib/flickarr/photo.rb +23 -0
- data/lib/flickarr/photo_set.rb +139 -0
- data/lib/flickarr/post.rb +253 -0
- data/lib/flickarr/profile.rb +177 -0
- data/lib/flickarr/rate_limiter.rb +24 -0
- data/lib/flickarr/version.rb +3 -0
- data/lib/flickarr/video.rb +65 -0
- data/lib/flickarr.rb +17 -0
- data/sig/flickarr.rbs +4 -0
- metadata +144 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Flickarr
|
|
2
|
+
class Client
|
|
3
|
+
class ProfileQuery
|
|
4
|
+
def initialize flickr:, user_id:, rate_limiter:
|
|
5
|
+
@flickr = flickr
|
|
6
|
+
@rate_limiter = rate_limiter
|
|
7
|
+
@user_id = user_id
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def info
|
|
11
|
+
@rate_limiter.track { @flickr.people.getInfo(user_id: @user_id) }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def profile
|
|
15
|
+
@rate_limiter.track { @flickr.profile.getProfile(user_id: @user_id) }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require 'flickr'
|
|
2
|
+
require_relative 'client/photo_query'
|
|
3
|
+
require_relative 'client/profile_query'
|
|
4
|
+
|
|
5
|
+
module Flickarr
|
|
6
|
+
class Client
|
|
7
|
+
attr_reader :flickr
|
|
8
|
+
|
|
9
|
+
def initialize config
|
|
10
|
+
raise ConfigError, 'api_key is required' if config.api_key.nil? || config.api_key.empty?
|
|
11
|
+
raise ConfigError, 'shared_secret is required' if config.shared_secret.nil? || config.shared_secret.empty?
|
|
12
|
+
|
|
13
|
+
@flickr = Flickr.new config.api_key, config.shared_secret
|
|
14
|
+
@rate_limiter = RateLimiter.new
|
|
15
|
+
|
|
16
|
+
return unless config.access_token && config.access_secret
|
|
17
|
+
|
|
18
|
+
@flickr.access_token = config.access_token
|
|
19
|
+
@flickr.access_secret = config.access_secret
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def collections user_id:
|
|
23
|
+
@rate_limiter.track do
|
|
24
|
+
flickr.collections.getTree(user_id: user_id)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def photo id:
|
|
29
|
+
PhotoQuery.new(flickr: flickr, id: id, rate_limiter: @rate_limiter)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
PHOTO_EXTRAS = %w[
|
|
33
|
+
date_taken
|
|
34
|
+
date_upload
|
|
35
|
+
description
|
|
36
|
+
geo
|
|
37
|
+
icon_server
|
|
38
|
+
last_update
|
|
39
|
+
license
|
|
40
|
+
machine_tags
|
|
41
|
+
media
|
|
42
|
+
o_dims
|
|
43
|
+
original_format
|
|
44
|
+
owner_name
|
|
45
|
+
path_alias
|
|
46
|
+
tags
|
|
47
|
+
url_c
|
|
48
|
+
url_l
|
|
49
|
+
url_m
|
|
50
|
+
url_n
|
|
51
|
+
url_o
|
|
52
|
+
url_q
|
|
53
|
+
url_s
|
|
54
|
+
url_sq
|
|
55
|
+
url_t
|
|
56
|
+
url_z
|
|
57
|
+
views
|
|
58
|
+
].join(',').freeze
|
|
59
|
+
|
|
60
|
+
def photos user_id:, page: 1, per_page: 100
|
|
61
|
+
@rate_limiter.track do
|
|
62
|
+
flickr.people.getPhotos(user_id: user_id, page: page, per_page: per_page, extras: PHOTO_EXTRAS)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
SET_PHOTO_EXTRAS = %w[
|
|
67
|
+
date_taken
|
|
68
|
+
date_upload
|
|
69
|
+
description
|
|
70
|
+
media
|
|
71
|
+
original_format
|
|
72
|
+
tags
|
|
73
|
+
url_o
|
|
74
|
+
].join(',').freeze
|
|
75
|
+
|
|
76
|
+
def set_photos photoset_id:, user_id:, page: 1, per_page: 500
|
|
77
|
+
@rate_limiter.track do
|
|
78
|
+
flickr.photosets.getPhotos(
|
|
79
|
+
photoset_id: photoset_id, user_id: user_id, page: page, per_page: per_page, extras: SET_PHOTO_EXTRAS
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def sets user_id:
|
|
85
|
+
@rate_limiter.track do
|
|
86
|
+
flickr.photosets.getList(user_id: user_id, per_page: 500)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def profile user_id:
|
|
91
|
+
ProfileQuery.new(flickr: flickr, user_id: user_id, rate_limiter: @rate_limiter)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'slugify'
|
|
4
|
+
require 'yaml'
|
|
5
|
+
|
|
6
|
+
module Flickarr
|
|
7
|
+
class Collection
|
|
8
|
+
COLLECTION_URL_PATTERN = %r{\Ahttps?://(?:www\.)?flickr\.com/photos/[^/]+/collections/(\d+)}
|
|
9
|
+
|
|
10
|
+
def self.id_from_url url
|
|
11
|
+
match = url.to_s.match COLLECTION_URL_PATTERN
|
|
12
|
+
match&.captures&.first
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :description,
|
|
16
|
+
:iconlarge,
|
|
17
|
+
:iconsmall,
|
|
18
|
+
:id,
|
|
19
|
+
:title
|
|
20
|
+
|
|
21
|
+
def initialize collection
|
|
22
|
+
@description = collection.description.to_s
|
|
23
|
+
@iconlarge = collection.iconlarge.to_s
|
|
24
|
+
@iconsmall = collection.iconsmall.to_s
|
|
25
|
+
@id = collection.id
|
|
26
|
+
@title = collection.title.to_s
|
|
27
|
+
@set_refs = collection.set
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def dirname
|
|
31
|
+
[id, slug].compact.join '_'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def sets_to_a
|
|
35
|
+
@set_refs.map do |s|
|
|
36
|
+
set_slug = s.title.to_s.slugify
|
|
37
|
+
set_dirname = [s.id, set_slug.empty? ? nil : set_slug].compact.join('_')
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
description: s.description.to_s,
|
|
41
|
+
id: s.id,
|
|
42
|
+
path: File.join('Sets', set_dirname),
|
|
43
|
+
title: s.title.to_s
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def slug
|
|
49
|
+
s = title.slugify
|
|
50
|
+
s.empty? ? nil : s
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def to_h
|
|
54
|
+
{
|
|
55
|
+
description: description,
|
|
56
|
+
iconlarge: iconlarge,
|
|
57
|
+
iconsmall: iconsmall,
|
|
58
|
+
id: id,
|
|
59
|
+
title: title
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def write archive_path:, overwrite: false
|
|
64
|
+
dir = collection_dir archive_path
|
|
65
|
+
json_path = File.join dir, 'collection.json'
|
|
66
|
+
existed = File.exist? json_path
|
|
67
|
+
|
|
68
|
+
return :skipped if existed && !overwrite
|
|
69
|
+
|
|
70
|
+
FileUtils.mkdir_p dir
|
|
71
|
+
write_collection_files dir: dir
|
|
72
|
+
write_sets_files dir: dir
|
|
73
|
+
|
|
74
|
+
existed ? :overwritten : :created
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def collection_dir archive_path
|
|
80
|
+
File.join archive_path, 'Collections', dirname
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def deep_stringify_keys obj
|
|
84
|
+
case obj
|
|
85
|
+
when Hash then obj.transform_keys(&:to_s).transform_values { deep_stringify_keys it }
|
|
86
|
+
when Array then obj.map { deep_stringify_keys it }
|
|
87
|
+
else obj
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def write_collection_files dir:
|
|
92
|
+
File.write File.join(dir, 'collection.json'), JSON.pretty_generate(to_h)
|
|
93
|
+
File.write File.join(dir, 'collection.yaml'), YAML.dump(to_h.transform_keys(&:to_s))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def write_sets_files dir:
|
|
97
|
+
refs = sets_to_a
|
|
98
|
+
|
|
99
|
+
File.write File.join(dir, 'sets.json'), JSON.pretty_generate(refs)
|
|
100
|
+
File.write File.join(dir, 'sets.yaml'), YAML.dump(deep_stringify_keys(refs))
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
module Flickarr
|
|
5
|
+
class Config
|
|
6
|
+
DEFAULT_LIBRARY_PATH = File.join(Dir.home, 'Pictures', 'Flickarr').freeze
|
|
7
|
+
|
|
8
|
+
attr_accessor :access_secret, :access_token, :api_key, :last_page_photos, :last_page_posts, :last_page_videos,
|
|
9
|
+
:library_path, :shared_secret, :total_collections, :total_photos, :total_sets, :total_videos,
|
|
10
|
+
:user_nsid, :username
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@access_secret = nil
|
|
14
|
+
@access_token = nil
|
|
15
|
+
@api_key = ENV.fetch('FLICKARR_API_KEY', nil)
|
|
16
|
+
@last_page_photos = nil
|
|
17
|
+
@last_page_posts = nil
|
|
18
|
+
@last_page_videos = nil
|
|
19
|
+
@library_path = DEFAULT_LIBRARY_PATH
|
|
20
|
+
@shared_secret = ENV.fetch('FLICKARR_SHARED_SECRET', nil)
|
|
21
|
+
@total_collections = nil
|
|
22
|
+
@total_photos = nil
|
|
23
|
+
@total_sets = nil
|
|
24
|
+
@total_videos = nil
|
|
25
|
+
@user_nsid = nil
|
|
26
|
+
@username = nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def save path
|
|
30
|
+
hash = to_h.transform_keys(&:to_s)
|
|
31
|
+
yaml = YAML.dump hash
|
|
32
|
+
dir = File.dirname path
|
|
33
|
+
|
|
34
|
+
FileUtils.mkdir_p dir
|
|
35
|
+
File.write path, yaml
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def archive_path
|
|
39
|
+
return nil if username.nil? || username.empty?
|
|
40
|
+
|
|
41
|
+
File.join library_path, username
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_h
|
|
45
|
+
{
|
|
46
|
+
access_secret: access_secret,
|
|
47
|
+
access_token: access_token,
|
|
48
|
+
api_key: api_key,
|
|
49
|
+
last_page_photos: last_page_photos,
|
|
50
|
+
last_page_posts: last_page_posts,
|
|
51
|
+
last_page_videos: last_page_videos,
|
|
52
|
+
library_path: library_path,
|
|
53
|
+
shared_secret: shared_secret,
|
|
54
|
+
total_collections: total_collections,
|
|
55
|
+
total_photos: total_photos,
|
|
56
|
+
total_sets: total_sets,
|
|
57
|
+
total_videos: total_videos,
|
|
58
|
+
user_nsid: user_nsid,
|
|
59
|
+
username: username
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def self.load path
|
|
64
|
+
config = new
|
|
65
|
+
return config unless File.exist?(path)
|
|
66
|
+
|
|
67
|
+
yaml = YAML.load_file(path, symbolize_names: true)
|
|
68
|
+
return config unless yaml.is_a?(Hash)
|
|
69
|
+
|
|
70
|
+
config.access_secret = yaml[:access_secret] if yaml[:access_secret]
|
|
71
|
+
config.access_token = yaml[:access_token] if yaml[:access_token]
|
|
72
|
+
config.api_key = yaml[:api_key] if yaml[:api_key]
|
|
73
|
+
config.last_page_photos = yaml[:last_page_photos] if yaml[:last_page_photos]
|
|
74
|
+
config.last_page_posts = yaml[:last_page_posts] if yaml[:last_page_posts]
|
|
75
|
+
config.last_page_videos = yaml[:last_page_videos] if yaml[:last_page_videos]
|
|
76
|
+
config.library_path = yaml[:library_path] if yaml[:library_path]
|
|
77
|
+
config.shared_secret = yaml[:shared_secret] if yaml[:shared_secret]
|
|
78
|
+
config.total_collections = yaml[:total_collections] if yaml[:total_collections]
|
|
79
|
+
config.total_photos = yaml[:total_photos] if yaml[:total_photos]
|
|
80
|
+
config.total_sets = yaml[:total_sets] if yaml[:total_sets]
|
|
81
|
+
config.total_videos = yaml[:total_videos] if yaml[:total_videos]
|
|
82
|
+
config.user_nsid = yaml[:user_nsid] if yaml[:user_nsid]
|
|
83
|
+
config.username = yaml[:username] if yaml[:username]
|
|
84
|
+
|
|
85
|
+
config
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Flickarr
|
|
2
|
+
class License
|
|
3
|
+
LICENSES = {
|
|
4
|
+
'0' => { name: 'All Rights Reserved', url: nil },
|
|
5
|
+
'1' => { name: 'CC BY-NC-SA 2.0', url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/' },
|
|
6
|
+
'2' => { name: 'CC BY-NC 2.0', url: 'https://creativecommons.org/licenses/by-nc/2.0/' },
|
|
7
|
+
'3' => { name: 'CC BY-NC-ND 2.0', url: 'https://creativecommons.org/licenses/by-nc-nd/2.0/' },
|
|
8
|
+
'4' => { name: 'CC BY 2.0', url: 'https://creativecommons.org/licenses/by/2.0/' },
|
|
9
|
+
'5' => { name: 'CC BY-SA 2.0', url: 'https://creativecommons.org/licenses/by-sa/2.0/' },
|
|
10
|
+
'6' => { name: 'CC BY-ND 2.0', url: 'https://creativecommons.org/licenses/by-nd/2.0/' },
|
|
11
|
+
'7' => { name: 'No Known Copyright Restrictions', url: 'https://www.flickr.com/commons/usage/' },
|
|
12
|
+
'8' => { name: 'United States Government Work', url: 'http://www.usa.gov/copyright.shtml' },
|
|
13
|
+
'9' => { name: 'CC0 1.0 Universal', url: 'https://creativecommons.org/publicdomain/zero/1.0/' },
|
|
14
|
+
'10' => { name: 'Public Domain Mark 1.0', url: 'https://creativecommons.org/publicdomain/mark/1.0/' }
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
17
|
+
attr_reader :id, :name, :url
|
|
18
|
+
|
|
19
|
+
def initialize id
|
|
20
|
+
@id = id.to_s
|
|
21
|
+
entry = LICENSES.fetch(@id, { name: 'Unknown', url: nil })
|
|
22
|
+
@name = entry[:name]
|
|
23
|
+
@url = entry[:url]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_h
|
|
27
|
+
{
|
|
28
|
+
id: id,
|
|
29
|
+
name: name,
|
|
30
|
+
url: url
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Flickarr
|
|
2
|
+
class Photo < Post
|
|
3
|
+
def initialize info:, sizes:, exif: nil
|
|
4
|
+
super
|
|
5
|
+
@extension = info.originalformat.to_s
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def download archive_path:
|
|
9
|
+
dir = post_dir archive_path
|
|
10
|
+
dest = File.join dir, "#{basename}.#{extension}"
|
|
11
|
+
|
|
12
|
+
FileUtils.mkdir_p dir
|
|
13
|
+
Down.download original_url, destination: dest
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def original_url
|
|
17
|
+
original = @sizes.find { it.label == 'Original' }
|
|
18
|
+
size = original || @sizes.last
|
|
19
|
+
|
|
20
|
+
size.source
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'slugify'
|
|
4
|
+
require 'yaml'
|
|
5
|
+
|
|
6
|
+
module Flickarr
|
|
7
|
+
class PhotoSet
|
|
8
|
+
SET_URL_PATTERN = %r{\Ahttps?://(?:www\.)?flickr\.com/photos/[^/]+/(?:sets|albums)/(\d+)}
|
|
9
|
+
|
|
10
|
+
def self.id_from_url url
|
|
11
|
+
match = url.to_s.match SET_URL_PATTERN
|
|
12
|
+
match&.captures&.first
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :count_comments,
|
|
16
|
+
:count_photos,
|
|
17
|
+
:count_videos,
|
|
18
|
+
:count_views,
|
|
19
|
+
:date_create,
|
|
20
|
+
:date_update,
|
|
21
|
+
:description,
|
|
22
|
+
:id,
|
|
23
|
+
:owner,
|
|
24
|
+
:primary,
|
|
25
|
+
:title,
|
|
26
|
+
:username
|
|
27
|
+
|
|
28
|
+
def initialize set:, photo_items:
|
|
29
|
+
@count_comments = set.count_comments.to_s
|
|
30
|
+
@count_photos = set.count_photos.to_i
|
|
31
|
+
@count_videos = set.count_videos.to_i
|
|
32
|
+
@count_views = set.count_views.to_s
|
|
33
|
+
@date_create = set.date_create.to_s
|
|
34
|
+
@date_update = set.date_update.to_s
|
|
35
|
+
@description = set.description.to_s
|
|
36
|
+
@id = set.id
|
|
37
|
+
@owner = set.owner.to_s
|
|
38
|
+
@primary = set.primary.to_s
|
|
39
|
+
@title = set.title.to_s
|
|
40
|
+
@username = set.username.to_s
|
|
41
|
+
@photo_items = photo_items
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def dirname
|
|
45
|
+
[id, slug].compact.join '_'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def photos_to_a
|
|
49
|
+
@photo_items.map do |item|
|
|
50
|
+
path = relative_photo_path item
|
|
51
|
+
{
|
|
52
|
+
datetaken: item.datetaken.to_s,
|
|
53
|
+
dateupload: item.dateupload.to_s,
|
|
54
|
+
id: item.id,
|
|
55
|
+
isprimary: item.isprimary.to_s == '1',
|
|
56
|
+
media: item.media.to_s,
|
|
57
|
+
path: path,
|
|
58
|
+
tags: item.tags.to_s,
|
|
59
|
+
title: item.title.to_s
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def slug
|
|
65
|
+
s = title.slugify
|
|
66
|
+
s.empty? ? nil : s
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def to_h
|
|
70
|
+
{
|
|
71
|
+
count_comments: count_comments,
|
|
72
|
+
count_photos: count_photos,
|
|
73
|
+
count_videos: count_videos,
|
|
74
|
+
count_views: count_views,
|
|
75
|
+
date_create: date_create,
|
|
76
|
+
date_update: date_update,
|
|
77
|
+
description: description,
|
|
78
|
+
id: id,
|
|
79
|
+
owner: owner,
|
|
80
|
+
primary: primary,
|
|
81
|
+
title: title,
|
|
82
|
+
username: username
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def write archive_path:, overwrite: false
|
|
87
|
+
dir = dir_for_set archive_path
|
|
88
|
+
json_path = File.join dir, 'set.json'
|
|
89
|
+
existed = File.exist? json_path
|
|
90
|
+
|
|
91
|
+
return :skipped if existed && !overwrite
|
|
92
|
+
|
|
93
|
+
FileUtils.mkdir_p dir
|
|
94
|
+
write_set_files dir: dir
|
|
95
|
+
write_photos_files dir: dir
|
|
96
|
+
|
|
97
|
+
existed ? :overwritten : :created
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def deep_stringify_keys obj
|
|
103
|
+
case obj
|
|
104
|
+
when Hash then obj.transform_keys(&:to_s).transform_values { deep_stringify_keys it }
|
|
105
|
+
when Array then obj.map { deep_stringify_keys it }
|
|
106
|
+
else obj
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def relative_photo_path item
|
|
111
|
+
ext = item.media.to_s == 'video' ? 'mp4' : item.originalformat.to_s
|
|
112
|
+
slug = item.title.to_s.slugify
|
|
113
|
+
base = [item.id, slug.empty? ? nil : slug].compact.join('_')
|
|
114
|
+
date = if item.datetakenunknown.to_i.zero?
|
|
115
|
+
Date.parse item.datetaken
|
|
116
|
+
else
|
|
117
|
+
Time.at(item.dateupload.to_i).to_date
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
File.join date.strftime('%Y/%m/%d'), "#{base}.#{ext}"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def dir_for_set archive_path
|
|
124
|
+
File.join archive_path, 'Sets', dirname
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def write_photos_files dir:
|
|
128
|
+
refs = photos_to_a
|
|
129
|
+
|
|
130
|
+
File.write File.join(dir, 'photos.json'), JSON.pretty_generate(refs)
|
|
131
|
+
File.write File.join(dir, 'photos.yaml'), YAML.dump(deep_stringify_keys(refs))
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def write_set_files dir:
|
|
135
|
+
File.write File.join(dir, 'set.json'), JSON.pretty_generate(to_h)
|
|
136
|
+
File.write File.join(dir, 'set.yaml'), YAML.dump(to_h.transform_keys(&:to_s))
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|