flickr_offline_gallery 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rspec +2 -0
- data/Gemfile +9 -0
- data/{LICENSE.txt → _LICENSE.txt} +0 -0
- data/bin/flickr_offline_gallery +2 -1
- data/erb/photo.html.erb +23 -2
- data/erb/photoset.html.erb +2 -1
- data/fixtures/vcr_cassettes/full_photo_sizes.yml +152 -0
- data/fixtures/vcr_cassettes/full_photo_sizes_with_janky_metadata.yml +147 -0
- data/fixtures/vcr_cassettes/image_downloads.yml +15096 -0
- data/fixtures/vcr_cassettes/init.yml +160 -0
- data/fixtures/vcr_cassettes/photo.yml +71 -0
- data/fixtures/vcr_cassettes/photo_sizes.yml +84 -0
- data/fixtures/vcr_cassettes/photo_with_janky_metadata.yml +70 -0
- data/fixtures/vcr_cassettes/photoset.yml +663 -0
- data/fixtures/vcr_cassettes/photset_downloader_spec.yml +1017 -0
- data/flickr_offline_gallery.gemspec +2 -1
- data/lib/flickr_offline_gallery/flickr_a_p_i.rb +23 -0
- data/lib/flickr_offline_gallery/gallery_generator.rb +26 -0
- data/lib/flickr_offline_gallery/path_manager.rb +37 -0
- data/lib/flickr_offline_gallery/photo.rb +28 -21
- data/lib/flickr_offline_gallery/photo_page.rb +23 -0
- data/lib/flickr_offline_gallery/photo_size.rb +9 -4
- data/lib/flickr_offline_gallery/photo_sizes.rb +11 -7
- data/lib/flickr_offline_gallery/photoset.rb +27 -6
- data/lib/flickr_offline_gallery/photoset_downloader.rb +21 -5
- data/lib/flickr_offline_gallery/photoset_index_page.rb +17 -0
- data/lib/flickr_offline_gallery/template_renderer.rb +42 -0
- data/lib/flickr_offline_gallery/verbose_puts.rb +8 -0
- data/lib/flickr_offline_gallery/version.rb +1 -1
- data/lib/flickr_offline_gallery.rb +7 -40
- data/spec/flickr_offline_gallery/gallery_generator_spec.rb +35 -0
- data/spec/flickr_offline_gallery/path_manager_spec.rb +34 -0
- data/spec/flickr_offline_gallery/photo_page_spec.rb +42 -0
- data/spec/flickr_offline_gallery/photo_size_spec.rb +32 -0
- data/spec/flickr_offline_gallery/photo_sizes_spec.rb +23 -0
- data/spec/flickr_offline_gallery/photo_spec.rb +81 -0
- data/spec/flickr_offline_gallery/photoset_downloader_spec.rb +27 -0
- data/spec/flickr_offline_gallery/photoset_spec.rb +35 -0
- data/spec/flickr_offline_gallery/template_renderer_spec.rb +51 -0
- data/spec/flickr_offline_gallery/verbose_puts_spec.rb +33 -0
- data/spec/spec_helper.rb +82 -0
- metadata +59 -5
@@ -0,0 +1,23 @@
|
|
1
|
+
module FlickrOfflineGallery
|
2
|
+
class FlickrAPI
|
3
|
+
def self.instance
|
4
|
+
@instance ||= FlickRaw::Flickr.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.get_photoset(photoset_id)
|
8
|
+
instance.photosets.getPhotos(:photoset_id => photoset_id).to_hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.get_photo_info(photo_id)
|
12
|
+
instance.photos.getInfo(:photo_id => photo_id).to_hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_photo_sizes(photo_id)
|
16
|
+
instance.photos.getSizes(:photo_id => photo_id).to_a
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# No thanks Flickraw. Not even once.
|
23
|
+
undef flickr
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module FlickrOfflineGallery
|
2
|
+
|
3
|
+
class GalleryGenerator
|
4
|
+
|
5
|
+
def initialize(photoset)
|
6
|
+
@photoset = photoset
|
7
|
+
end
|
8
|
+
|
9
|
+
def render_photoset(size)
|
10
|
+
download_images(size)
|
11
|
+
render_photo_pages
|
12
|
+
PhotosetIndexPage.new(@photoset).write
|
13
|
+
end
|
14
|
+
|
15
|
+
def download_images(size = "medium_800")
|
16
|
+
PhotosetDownloader.new(@photoset, size).download
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_photo_pages
|
20
|
+
@photoset.photos.each do |photo|
|
21
|
+
PhotoPage.new(photo).write
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module FlickrOfflineGallery
|
2
|
+
class PathManager
|
3
|
+
|
4
|
+
attr_reader :base_path
|
5
|
+
|
6
|
+
def initialize(base_path, slug)
|
7
|
+
@base_path = base_path
|
8
|
+
@slug = slug
|
9
|
+
end
|
10
|
+
|
11
|
+
def photo_output_path
|
12
|
+
File.join(base_path, @slug)
|
13
|
+
end
|
14
|
+
|
15
|
+
def index_page
|
16
|
+
"#{photo_output_path}.html"
|
17
|
+
end
|
18
|
+
|
19
|
+
def full_path_for(photo_id, extension)
|
20
|
+
File.join(photo_output_path, filename_for_photo(photo_id, extension))
|
21
|
+
end
|
22
|
+
|
23
|
+
def relative_path_for(photo_id, extension)
|
24
|
+
File.join(@slug, filename_for_photo(photo_id, extension))
|
25
|
+
end
|
26
|
+
|
27
|
+
def filename_for_photo(photo_id, extension)
|
28
|
+
"#{photo_id}.#{extension}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def back_to_index
|
32
|
+
"../#{@slug}.html"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -1,46 +1,53 @@
|
|
1
1
|
module FlickrOfflineGallery
|
2
2
|
class Photo
|
3
|
+
include VerbosePuts
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(horrible_flickraw_response_junk, photoset_id = nil)
|
5
|
+
def initialize(horrible_flickraw_response_junk, args = {})
|
6
|
+
@path_manager = args[:path_manager]
|
7
7
|
@id = horrible_flickraw_response_junk["id"]
|
8
|
-
@
|
9
|
-
@set = photoset_id
|
8
|
+
@photoset_id = args[:photoset_id]
|
10
9
|
eager_load
|
11
|
-
|
10
|
+
verbose_puts %(Fetched data about photo #{@id}: "#{title}")
|
12
11
|
end
|
13
12
|
|
14
13
|
def title
|
15
14
|
info.title
|
16
15
|
end
|
17
16
|
|
18
|
-
def date
|
19
|
-
@date ||= DateTime.parse(info.dates["taken"])
|
20
|
-
end
|
21
|
-
|
22
17
|
def url
|
23
|
-
if
|
24
|
-
"#{base_url}in/set-#{
|
18
|
+
if @photoset_id
|
19
|
+
"#{base_url}in/set-#{@photoset_id}"
|
25
20
|
else
|
26
21
|
base_url
|
27
22
|
end
|
28
23
|
end
|
29
24
|
|
25
|
+
def base_url
|
26
|
+
@base_url ||= info.urls.find{|u| u["type"] == "photopage"}["_content"]
|
27
|
+
end
|
28
|
+
|
30
29
|
def img_filename
|
31
|
-
|
30
|
+
@path_manager.filename_for_photo(@id, :jpg)
|
32
31
|
end
|
33
32
|
|
34
|
-
def
|
35
|
-
|
33
|
+
def full_jpg_path
|
34
|
+
@path_manager.full_path_for(@id, :jpg)
|
36
35
|
end
|
37
36
|
|
38
|
-
def
|
39
|
-
|
37
|
+
def full_html_path
|
38
|
+
@path_manager.full_path_for(@id, :html)
|
40
39
|
end
|
41
40
|
|
42
|
-
def
|
43
|
-
@
|
41
|
+
def relative_jpg_path
|
42
|
+
@path_manager.relative_path_for(@id, :jpg)
|
43
|
+
end
|
44
|
+
|
45
|
+
def relative_html_path
|
46
|
+
@path_manager.relative_path_for(@id, :html)
|
47
|
+
end
|
48
|
+
|
49
|
+
def back_to_index_url
|
50
|
+
@path_manager.back_to_index
|
44
51
|
end
|
45
52
|
|
46
53
|
def sizes
|
@@ -59,11 +66,11 @@ module FlickrOfflineGallery
|
|
59
66
|
end
|
60
67
|
|
61
68
|
def info
|
62
|
-
@info ||= OpenStruct.new(
|
69
|
+
@info ||= OpenStruct.new(FlickrAPI.get_photo_info(@id))
|
63
70
|
end
|
64
71
|
|
65
72
|
def raw_sizes
|
66
|
-
@raw_sizes ||=
|
73
|
+
@raw_sizes ||= FlickrAPI.get_photo_sizes(@id)
|
67
74
|
end
|
68
75
|
|
69
76
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FlickrOfflineGallery
|
2
|
+
class PhotoPage < TemplateRenderer
|
3
|
+
|
4
|
+
def initialize(photo)
|
5
|
+
@photo = photo
|
6
|
+
super("photo")
|
7
|
+
end
|
8
|
+
|
9
|
+
def render
|
10
|
+
render_erb(:back_to_index_page => @photo.back_to_index_url,
|
11
|
+
:image_url => @photo.img_filename,
|
12
|
+
:sizes => @photo.sizes,
|
13
|
+
:photo_page_url => @photo.url,
|
14
|
+
:title => @photo.title,
|
15
|
+
:author => @photo.author)
|
16
|
+
end
|
17
|
+
|
18
|
+
def write
|
19
|
+
write_file(@photo.full_html_path)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -1,8 +1,13 @@
|
|
1
1
|
module FlickrOfflineGallery
|
2
|
-
class PhotoSize
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
class PhotoSize
|
3
|
+
|
4
|
+
attr_reader :label, :width, :height, :url
|
5
|
+
|
6
|
+
def initialize(flickraw_response)
|
7
|
+
@label = flickraw_response.label
|
8
|
+
@height = flickraw_response.height
|
9
|
+
@width = flickraw_response.width
|
10
|
+
@url = flickraw_response.source
|
6
11
|
end
|
7
12
|
|
8
13
|
def key
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module FlickrOfflineGallery
|
2
|
-
class PhotoSizes
|
3
|
-
|
2
|
+
class PhotoSizes
|
3
|
+
|
4
4
|
def initialize(raw_sizes)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
@sizes = Hash[raw_sizes.map do |s|
|
6
|
+
size = PhotoSize.new(s)
|
7
|
+
[size.key, size]
|
8
|
+
end]
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
@sizes[key.to_s]
|
9
13
|
end
|
10
14
|
|
11
15
|
def each
|
12
|
-
|
16
|
+
@sizes.values.each do |value|
|
13
17
|
yield(value)
|
14
18
|
end
|
15
19
|
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module FlickrOfflineGallery
|
2
2
|
class Photoset
|
3
|
-
|
3
|
+
|
4
|
+
include VerbosePuts
|
5
|
+
|
6
|
+
def initialize(photoset_id, args = {})
|
4
7
|
@photoset_id = photoset_id
|
5
|
-
|
8
|
+
@output_base_path = args[:output_path] || "."
|
9
|
+
eager_load
|
6
10
|
end
|
7
11
|
|
8
12
|
def username
|
@@ -14,19 +18,36 @@ module FlickrOfflineGallery
|
|
14
18
|
end
|
15
19
|
|
16
20
|
def slug
|
17
|
-
title.downcase.
|
21
|
+
title.downcase.tr_s("^a-z0-9", "-")
|
18
22
|
end
|
19
23
|
|
20
24
|
def photos
|
21
25
|
raise "photoset has more than 500 images and I'm too lazy to handle that right now" if info.pages > 1
|
22
|
-
|
23
|
-
@photos ||= info.photo.map
|
26
|
+
verbose_puts "Initializing photoset... " unless @photos
|
27
|
+
@photos ||= info.photo.map do |raw_response|
|
28
|
+
Photo.new(raw_response,
|
29
|
+
:photoset_id => @photoset_id,
|
30
|
+
:path_manager => path_manager)
|
31
|
+
end.tap{ verbose_puts "Finished initializing photoset!" }
|
32
|
+
end
|
33
|
+
|
34
|
+
def index_page_filename
|
35
|
+
path_manager.index_page
|
24
36
|
end
|
25
37
|
|
26
38
|
private
|
27
39
|
|
40
|
+
def path_manager
|
41
|
+
PathManager.new(@output_base_path, slug)
|
42
|
+
end
|
43
|
+
|
44
|
+
def eager_load
|
45
|
+
info
|
46
|
+
photos
|
47
|
+
end
|
48
|
+
|
28
49
|
def info
|
29
|
-
@info ||= OpenStruct.new(
|
50
|
+
@info ||= OpenStruct.new(FlickrAPI.get_photoset(@photoset_id))
|
30
51
|
end
|
31
52
|
end
|
32
53
|
end
|
@@ -1,5 +1,9 @@
|
|
1
|
+
require 'httparty'
|
1
2
|
module FlickrOfflineGallery
|
2
3
|
class PhotosetDownloader
|
4
|
+
|
5
|
+
include VerbosePuts
|
6
|
+
|
3
7
|
def initialize(photoset, size)
|
4
8
|
@photoset = photoset
|
5
9
|
@size = size
|
@@ -7,14 +11,13 @@ module FlickrOfflineGallery
|
|
7
11
|
|
8
12
|
def download
|
9
13
|
photos.each do |photo|
|
10
|
-
url = photo.sizes[@size].
|
11
|
-
local_path = photo.
|
14
|
+
url = photo.sizes[@size].url
|
15
|
+
local_path = photo.full_jpg_path
|
12
16
|
FileUtils.mkdir_p(File.dirname(local_path))
|
13
17
|
|
14
18
|
unless File.exist?(local_path)
|
15
|
-
|
16
|
-
|
17
|
-
puts "Downloaded #{local_path}"
|
19
|
+
download_file(url, local_path)
|
20
|
+
verbose_puts "Downloaded #{local_path}"
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -25,5 +28,18 @@ module FlickrOfflineGallery
|
|
25
28
|
@photoset.photos
|
26
29
|
end
|
27
30
|
|
31
|
+
def download_file(url, destination)
|
32
|
+
resp = http_get(url)
|
33
|
+
File.open(destination, "wb") do |file|
|
34
|
+
file.write(resp.body)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def http_get(url)
|
39
|
+
response = HTTParty.get(url)
|
40
|
+
raise "unhandled response code: #{response.code}" unless response.code == 200
|
41
|
+
response
|
42
|
+
end
|
43
|
+
|
28
44
|
end
|
29
45
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module FlickrOfflineGallery
|
2
|
+
class PhotosetIndexPage < TemplateRenderer
|
3
|
+
|
4
|
+
def initialize(photoset)
|
5
|
+
@photoset = photoset
|
6
|
+
super("photoset")
|
7
|
+
end
|
8
|
+
|
9
|
+
def render
|
10
|
+
render_erb(:photoset => @photoset, :photos => @photoset.photos, :size => "medium")
|
11
|
+
end
|
12
|
+
|
13
|
+
def write
|
14
|
+
write_file(@photoset.index_page_filename)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module FlickrOfflineGallery
|
2
|
+
class TemplateRenderer
|
3
|
+
|
4
|
+
include VerbosePuts
|
5
|
+
|
6
|
+
def initialize(template)
|
7
|
+
@template = template
|
8
|
+
end
|
9
|
+
|
10
|
+
def template_path
|
11
|
+
File.expand_path("../../../erb/#{@template}.html.erb",__FILE__)
|
12
|
+
end
|
13
|
+
|
14
|
+
def template_directory
|
15
|
+
File.expand_path("../../../erb/", __FILE__)
|
16
|
+
end
|
17
|
+
|
18
|
+
def template_contents
|
19
|
+
raise "Unknown template: #{template_path}" unless File.exist?(template_path)
|
20
|
+
@template_content ||= File.read(template_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_erb(locals)
|
24
|
+
ERB.new(template_contents).result(OpenStruct.new(locals).instance_eval { binding })
|
25
|
+
end
|
26
|
+
|
27
|
+
def render
|
28
|
+
raise "not implemented"
|
29
|
+
end
|
30
|
+
|
31
|
+
def write
|
32
|
+
raise "not implemented"
|
33
|
+
end
|
34
|
+
|
35
|
+
def write_file(filename)
|
36
|
+
File.open(filename, 'w') do |file|
|
37
|
+
file.write render
|
38
|
+
end
|
39
|
+
verbose_puts "Wrote out #{filename}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -3,52 +3,19 @@ require 'erb'
|
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
5
|
require "flickr_offline_gallery/version"
|
6
|
+
require "flickr_offline_gallery/verbose_puts"
|
7
|
+
require "flickr_offline_gallery/path_manager"
|
6
8
|
require "flickr_offline_gallery/photo_size"
|
7
9
|
require "flickr_offline_gallery/photo_sizes"
|
8
10
|
require "flickr_offline_gallery/photo"
|
9
11
|
require "flickr_offline_gallery/photoset"
|
10
12
|
require "flickr_offline_gallery/photoset_downloader"
|
13
|
+
require "flickr_offline_gallery/flickr_a_p_i"
|
14
|
+
require "flickr_offline_gallery/template_renderer"
|
15
|
+
require "flickr_offline_gallery/photo_page"
|
16
|
+
require "flickr_offline_gallery/photoset_index_page"
|
17
|
+
require "flickr_offline_gallery/gallery_generator"
|
11
18
|
|
12
19
|
module FlickrOfflineGallery
|
13
|
-
class Variables
|
14
|
-
class << self
|
15
|
-
attr_accessor :slug
|
16
|
-
end
|
17
|
-
end
|
18
20
|
|
19
|
-
def self.download(photoset, size = "medium_800")
|
20
|
-
PhotosetDownloader.new(photoset, size).download
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.render_photoset(photoset, size)
|
24
|
-
download(photoset, size)
|
25
|
-
render_photo_pages(photoset)
|
26
|
-
render_photoset_index_page(photoset)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.render_photoset_index_page(photoset)
|
30
|
-
File.open("#{photoset.slug}.html", "w") do |f|
|
31
|
-
f.write render_erb("photoset", :photoset => photoset, :photos => photoset.photos, :size => "medium")
|
32
|
-
end
|
33
|
-
puts "#{photoset.slug}.html"
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.render_photo_pages(photoset)
|
37
|
-
photoset.photos.each do |p|
|
38
|
-
render_photo_page(p)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.render_photo_page(photo)
|
43
|
-
File.open(photo.local_html_path, "w") do |f|
|
44
|
-
f.write render_erb("photo", :source => photo.img_filename, :sizes => photo.sizes, :photo_url => photo.url, :title => photo.title, :author => photo.author)
|
45
|
-
end
|
46
|
-
puts "Rendered #{photo.local_html_path}"
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.render_erb(template, locals)
|
50
|
-
full_template_path = File.expand_path("../../erb/#{template}.html.erb",__FILE__)
|
51
|
-
raise "unknown template: #{full_template_path}" unless File.exist?(full_template_path)
|
52
|
-
ERB.new(File.read(full_template_path)).result(OpenStruct.new(locals).instance_eval { binding })
|
53
|
-
end
|
54
21
|
end
|