jekyll-flickr-utils 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/lib/flickr_downloader.rb +172 -0
- data/lib/jekyll-flickr-utils.rb +5 -0
- data/lib/post_image.rb +92 -0
- metadata +120 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5ecf9cfe481ab49cbdbe3cdda762544467f75be8b88f548fa4504953e804067e
|
4
|
+
data.tar.gz: 258a913fb9833ad2d12608860f6b3a9d0e4a542ca4c3f04b198223aae824a9c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d23949729a14f7375428dc8d9731f0adee3f8b88e98743abaf6eddd8d488af3ddf8309773163bfcfd9484172cf282eb1a45032e0d086ef6f41496f53500a1d6d
|
7
|
+
data.tar.gz: 39eb671a361ab019ffe80b50f50caeff39b58f41ec2759c5f31280406e4f304abcfb8665d51a58acd22d853cef0c5e11ae92a5832a456f0d631bb67c82d90cd7
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014-present Alfred Xing and the jekyll-archives contributors
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'down'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'flickr'
|
7
|
+
require 'jekyll'
|
8
|
+
require 'open-uri'
|
9
|
+
require 'sorbet-runtime'
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
module FlickrDownloader
|
13
|
+
class Generator < Jekyll::Generator
|
14
|
+
extend T::Sig
|
15
|
+
|
16
|
+
LOG_TOPIC = 'Flickr Downloader:'
|
17
|
+
JEKYLL_ROOT = T.let(Jekyll.configuration.source({}), String)
|
18
|
+
MANIFEST_FILE_PATH = T.let("#{JEKYLL_ROOT}/_data/flickr_photosets.yaml", String)
|
19
|
+
|
20
|
+
ConfigType = T.type_alias { T::Hash[String, T.untyped] }
|
21
|
+
ManifestType = T.type_alias { T::Hash[String, T::Hash[String, String]] }
|
22
|
+
|
23
|
+
DEFAULTS = T.let(
|
24
|
+
{
|
25
|
+
'enabled' => false,
|
26
|
+
'image_root' => 'assets/images/flickr_photosets',
|
27
|
+
'force_refresh' => false,
|
28
|
+
'image_size' => 'url_k'
|
29
|
+
}.freeze,
|
30
|
+
ConfigType
|
31
|
+
)
|
32
|
+
|
33
|
+
sig { params(config: ConfigType).void }
|
34
|
+
def initialize(config = {})
|
35
|
+
super
|
36
|
+
|
37
|
+
@config = T.let(DEFAULTS.merge(config.fetch('flickr_downloader', {})), ConfigType)
|
38
|
+
|
39
|
+
@flickr = T.let(nil, T.nilable(Flickr))
|
40
|
+
|
41
|
+
return unless enabled?
|
42
|
+
|
43
|
+
@flickr = Flickr.new(@config['api_key'], @config['shared_secret'])
|
44
|
+
@flickr.access_token = @config['access_token']
|
45
|
+
@flickr.access_secret = @config['access_secret']
|
46
|
+
end
|
47
|
+
|
48
|
+
sig { returns(T::Boolean) }
|
49
|
+
def enabled?
|
50
|
+
@config['enabled']
|
51
|
+
end
|
52
|
+
|
53
|
+
sig { params(site: Jekyll::Site).void }
|
54
|
+
def generate(site)
|
55
|
+
unless enabled?
|
56
|
+
Jekyll.logger.warn(LOG_TOPIC, 'Plugin disabled via config!')
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
posts = site.posts.docs.select do |post|
|
61
|
+
!post.data.fetch('disable_flickr_download', false) && post.data.fetch('flickr_photoset_id', nil)
|
62
|
+
end
|
63
|
+
|
64
|
+
FileUtils.touch(MANIFEST_FILE_PATH) if posts && !File.exist?(MANIFEST_FILE_PATH)
|
65
|
+
|
66
|
+
posts.each do |post|
|
67
|
+
flickr_photoset_id = post.data['flickr_photoset_id']
|
68
|
+
|
69
|
+
if flickr_photoset_id.is_a?(Array)
|
70
|
+
flickr_photoset_id.each { |photoset_id| download_photoset(photoset_id.to_s, post) }
|
71
|
+
elsif flickr_photoset_id
|
72
|
+
download_photoset(flickr_photoset_id.to_s, post)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
sig { params(flickr_photoset_id: String).returns(T::Boolean) }
|
78
|
+
private def should_download?(flickr_photoset_id)
|
79
|
+
data = YAML.load_file(MANIFEST_FILE_PATH) || {}
|
80
|
+
# Ensure we treat the photoset ID as a String instead of an integer
|
81
|
+
data = data.transform_keys(&:to_s)
|
82
|
+
data.fetch(flickr_photoset_id, nil).nil? || @config['force_refresh']
|
83
|
+
end
|
84
|
+
|
85
|
+
sig { params(url: String, destination: String).void }
|
86
|
+
private def download_photo(url, destination)
|
87
|
+
Down.download(url, destination: "#{JEKYLL_ROOT}/#{destination}")
|
88
|
+
end
|
89
|
+
|
90
|
+
sig { params(manifest: ManifestType).void }
|
91
|
+
private def write_manifest_file(manifest)
|
92
|
+
data = YAML.load_file(MANIFEST_FILE_PATH) || {}
|
93
|
+
data = data.merge(manifest)
|
94
|
+
File.write(MANIFEST_FILE_PATH, YAML.dump(data))
|
95
|
+
end
|
96
|
+
|
97
|
+
sig { params(photoset_id: String, directory: String).returns(ManifestType) }
|
98
|
+
private def download_photoset_photos(photoset_id, directory)
|
99
|
+
directory = directory.chomp('/')
|
100
|
+
|
101
|
+
Jekyll.logger.info(LOG_TOPIC, "Downloading photos from Flickr photoset #{photoset_id} to #{directory}...")
|
102
|
+
|
103
|
+
image_size = @config['image_size']
|
104
|
+
# NOTE: Sorbet cannot find the dynamically-generated methods.
|
105
|
+
photoset = T.let(@flickr, T.untyped).photosets.getPhotos(
|
106
|
+
photoset_id: photoset_id,
|
107
|
+
extras: "description,url_o,#{image_size}"
|
108
|
+
)
|
109
|
+
|
110
|
+
manifest_images = {}
|
111
|
+
primary_photo_id = photoset.primary
|
112
|
+
primary_photo_filename = T.let(nil, T.nilable(String))
|
113
|
+
|
114
|
+
photoset.photo.each_with_index do |photo, index|
|
115
|
+
# NOTE: If the image is too small, Flickr may not have a URL matching the requested size.
|
116
|
+
# Fall back to the original size in such cases.
|
117
|
+
url = photo[image_size] || photo['url_o']
|
118
|
+
filename = format("#{directory}/%03d.jpg", (index + 1))
|
119
|
+
|
120
|
+
primary_photo_filename = filename if photo.id == primary_photo_id
|
121
|
+
|
122
|
+
manifest_images[filename] = {
|
123
|
+
'metadata' => {
|
124
|
+
'title' => photo.title,
|
125
|
+
'description' => photo.description
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
download_photo(url, filename)
|
130
|
+
end
|
131
|
+
|
132
|
+
manifest = {
|
133
|
+
photoset_id => {
|
134
|
+
'title' => photoset.title,
|
135
|
+
'primary_image' => primary_photo_filename,
|
136
|
+
'images' => manifest_images
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
Jekyll
|
141
|
+
.logger
|
142
|
+
.info(
|
143
|
+
LOG_TOPIC,
|
144
|
+
"Finished downloading #{manifest_images.length} photos from Flickr photoset #{photoset_id} to #{directory}."
|
145
|
+
)
|
146
|
+
|
147
|
+
manifest
|
148
|
+
end
|
149
|
+
|
150
|
+
sig { params(flickr_photoset_id: String, post: T.untyped).void }
|
151
|
+
private def download_photoset(flickr_photoset_id, post)
|
152
|
+
unless should_download?(flickr_photoset_id)
|
153
|
+
post_name = T.must(%r{_posts/(?<name>.+)\.md}.match(post.relative_path))['name']
|
154
|
+
Jekyll
|
155
|
+
.logger
|
156
|
+
.warn(
|
157
|
+
LOG_TOPIC,
|
158
|
+
# rubocop: disable Layout/LineLength
|
159
|
+
"Photos already downloaded for Flickr photoset #{flickr_photoset_id}, referenced by #{post_name}. Moving on."
|
160
|
+
# rubocop: enable Layout/LineLength
|
161
|
+
)
|
162
|
+
return
|
163
|
+
end
|
164
|
+
|
165
|
+
post_image_root = "#{@config['image_root']}/#{flickr_photoset_id}"
|
166
|
+
FileUtils.mkdir_p(post_image_root)
|
167
|
+
|
168
|
+
manifest = download_photoset_photos(flickr_photoset_id, post_image_root)
|
169
|
+
write_manifest_file(manifest)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
data/lib/post_image.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'sorbet-runtime'
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
module FlickrHelpers
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
PhotosetId = T.type_alias { Integer }
|
11
|
+
|
12
|
+
sig { params(photoset_id: T.any(PhotosetId, T::Array[PhotosetId])).returns(PhotosetId) }
|
13
|
+
def self.get_first_photoset_id(photoset_id)
|
14
|
+
photoset_id = T.must(photoset_id.first) if photoset_id.is_a?(Array)
|
15
|
+
|
16
|
+
photoset_id
|
17
|
+
end
|
18
|
+
|
19
|
+
sig { params(photoset_id: PhotosetId).returns(T.nilable(String)) }
|
20
|
+
def self.get_photoset_primary_photo(photoset_id)
|
21
|
+
path = Jekyll.sites.first.data['flickr_photosets'].fetch(photoset_id, {}).fetch('primary_image', nil)
|
22
|
+
path.nil? ? nil : "/#{path}"
|
23
|
+
rescue KeyError
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module PostImage
|
29
|
+
extend T::Sig
|
30
|
+
|
31
|
+
JEKYLL_ROOT = T.let(Jekyll.configuration.source({}), String)
|
32
|
+
|
33
|
+
sig { params(post: T.untyped).returns(T.nilable(String)) }
|
34
|
+
def post_image(post)
|
35
|
+
item_id = post.fetch('relative_path')
|
36
|
+
Jekyll.logger.info('Post Image:', "Retrieving post image for #{item_id}")
|
37
|
+
|
38
|
+
image = post.fetch('image') { flickr_primary_photo(post) }
|
39
|
+
image = nil unless image && file_exists?(image)
|
40
|
+
|
41
|
+
if image.nil? && item_id.start_with?('_posts')
|
42
|
+
Jekyll.logger.warn('Post Image:', "Missing post image for #{item_id}")
|
43
|
+
end
|
44
|
+
|
45
|
+
image
|
46
|
+
end
|
47
|
+
|
48
|
+
sig { params(post: T.untyped).returns(T::Boolean) }
|
49
|
+
def post_has_image(post)
|
50
|
+
post_image = post_image(post)
|
51
|
+
!!post_image && file_exists?(post_image)
|
52
|
+
rescue KeyError
|
53
|
+
false
|
54
|
+
end
|
55
|
+
|
56
|
+
sig { params(post: T.untyped).returns(T::Boolean) }
|
57
|
+
def show_flickr_gallery(post)
|
58
|
+
post.key?('flickr_photoset_id') && !post.fetch('hide_flickr_gallery',
|
59
|
+
false) && !post.fetch('hide_post_gallery', false)
|
60
|
+
end
|
61
|
+
|
62
|
+
sig { params(post: T.untyped).returns(T::Boolean) }
|
63
|
+
def show_post_gallery(post)
|
64
|
+
!post.fetch('hide_post_gallery', false)
|
65
|
+
end
|
66
|
+
|
67
|
+
sig { params(path: String).returns(T::Boolean) }
|
68
|
+
private def file_exists?(path)
|
69
|
+
full_path = "#{JEKYLL_ROOT}#{path}"
|
70
|
+
File.exist?(full_path)
|
71
|
+
end
|
72
|
+
|
73
|
+
sig { params(post: T.untyped).returns(T.nilable(String)) }
|
74
|
+
private def flickr_primary_photo(post)
|
75
|
+
photoset_id = FlickrHelpers.get_first_photoset_id(post.fetch('flickr_photoset_id'))
|
76
|
+
FlickrHelpers.get_photoset_primary_photo(photoset_id)
|
77
|
+
rescue KeyError
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
Liquid::Template.register_filter(Jekyll::PostImage)
|
84
|
+
|
85
|
+
Jekyll::Hooks.register :posts, :pre_render do |post|
|
86
|
+
# Set the image field from Flickr data so jekyll-seo-tag renders the correct meta tags.
|
87
|
+
if !post.data.key?('image') && post.data.key?('flickr_photoset_id')
|
88
|
+
photoset_id = Jekyll::FlickrHelpers.get_first_photoset_id(post.data.fetch('flickr_photoset_id'))
|
89
|
+
image_path = Jekyll::FlickrHelpers.get_photoset_primary_photo(photoset_id)
|
90
|
+
post.data['image'] = image_path
|
91
|
+
end
|
92
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jekyll-flickr-utils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Clinton Blackburn
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-11-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: jekyll
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.3'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.3'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: down
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '5.0'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '6.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '5.0'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '6.0'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: flickr
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.0'
|
60
|
+
- - "<"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '3.0'
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '2.0'
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '3.0'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: sorbet-runtime
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
type: :runtime
|
81
|
+
prerelease: false
|
82
|
+
version_requirements: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
description:
|
88
|
+
email:
|
89
|
+
executables: []
|
90
|
+
extensions: []
|
91
|
+
extra_rdoc_files: []
|
92
|
+
files:
|
93
|
+
- LICENSE
|
94
|
+
- lib/flickr_downloader.rb
|
95
|
+
- lib/jekyll-flickr-utils.rb
|
96
|
+
- lib/post_image.rb
|
97
|
+
homepage:
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.7.0
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubygems_version: 3.1.6
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Download images from Flickr
|
120
|
+
test_files: []
|