flickr_offline_gallery 0.0.2 → 0.0.3

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +9 -0
  5. data/{LICENSE.txt → _LICENSE.txt} +0 -0
  6. data/bin/flickr_offline_gallery +2 -1
  7. data/erb/photo.html.erb +23 -2
  8. data/erb/photoset.html.erb +2 -1
  9. data/fixtures/vcr_cassettes/full_photo_sizes.yml +152 -0
  10. data/fixtures/vcr_cassettes/full_photo_sizes_with_janky_metadata.yml +147 -0
  11. data/fixtures/vcr_cassettes/image_downloads.yml +15096 -0
  12. data/fixtures/vcr_cassettes/init.yml +160 -0
  13. data/fixtures/vcr_cassettes/photo.yml +71 -0
  14. data/fixtures/vcr_cassettes/photo_sizes.yml +84 -0
  15. data/fixtures/vcr_cassettes/photo_with_janky_metadata.yml +70 -0
  16. data/fixtures/vcr_cassettes/photoset.yml +663 -0
  17. data/fixtures/vcr_cassettes/photset_downloader_spec.yml +1017 -0
  18. data/flickr_offline_gallery.gemspec +2 -1
  19. data/lib/flickr_offline_gallery/flickr_a_p_i.rb +23 -0
  20. data/lib/flickr_offline_gallery/gallery_generator.rb +26 -0
  21. data/lib/flickr_offline_gallery/path_manager.rb +37 -0
  22. data/lib/flickr_offline_gallery/photo.rb +28 -21
  23. data/lib/flickr_offline_gallery/photo_page.rb +23 -0
  24. data/lib/flickr_offline_gallery/photo_size.rb +9 -4
  25. data/lib/flickr_offline_gallery/photo_sizes.rb +11 -7
  26. data/lib/flickr_offline_gallery/photoset.rb +27 -6
  27. data/lib/flickr_offline_gallery/photoset_downloader.rb +21 -5
  28. data/lib/flickr_offline_gallery/photoset_index_page.rb +17 -0
  29. data/lib/flickr_offline_gallery/template_renderer.rb +42 -0
  30. data/lib/flickr_offline_gallery/verbose_puts.rb +8 -0
  31. data/lib/flickr_offline_gallery/version.rb +1 -1
  32. data/lib/flickr_offline_gallery.rb +7 -40
  33. data/spec/flickr_offline_gallery/gallery_generator_spec.rb +35 -0
  34. data/spec/flickr_offline_gallery/path_manager_spec.rb +34 -0
  35. data/spec/flickr_offline_gallery/photo_page_spec.rb +42 -0
  36. data/spec/flickr_offline_gallery/photo_size_spec.rb +32 -0
  37. data/spec/flickr_offline_gallery/photo_sizes_spec.rb +23 -0
  38. data/spec/flickr_offline_gallery/photo_spec.rb +81 -0
  39. data/spec/flickr_offline_gallery/photoset_downloader_spec.rb +27 -0
  40. data/spec/flickr_offline_gallery/photoset_spec.rb +35 -0
  41. data/spec/flickr_offline_gallery/template_renderer_spec.rb +51 -0
  42. data/spec/flickr_offline_gallery/verbose_puts_spec.rb +33 -0
  43. data/spec/spec_helper.rb +82 -0
  44. metadata +59 -5
@@ -20,5 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.4"
22
22
  spec.add_development_dependency "rake"
23
- spec.add_dependency "flickraw"
23
+ spec.add_runtime_dependency "flickraw"
24
+ spec.add_runtime_dependency "httparty"
24
25
  end
@@ -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
- attr_reader :id, :secret, :set
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
- @secret = horrible_flickraw_response_junk["secret"]
9
- @set = photoset_id
8
+ @photoset_id = args[:photoset_id]
10
9
  eager_load
11
- puts "Fetched data about photo #{title}"
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 set
24
- "#{base_url}in/set-#{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
- "#{id}.jpg"
30
+ @path_manager.filename_for_photo(@id, :jpg)
32
31
  end
33
32
 
34
- def local_jpg_path
35
- "#{::FlickrOfflineGallery::Variables.slug}/#{img_filename}"
33
+ def full_jpg_path
34
+ @path_manager.full_path_for(@id, :jpg)
36
35
  end
37
36
 
38
- def local_html_path
39
- local_jpg_path.sub(/\.jpg$/, ".html")
37
+ def full_html_path
38
+ @path_manager.full_path_for(@id, :html)
40
39
  end
41
40
 
42
- def base_url
43
- @base_url ||= info.urls.find{|u| u["type"] == "photopage"}["_content"]
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(flickr.photos.getInfo(:photo_id => @id).to_hash)
69
+ @info ||= OpenStruct.new(FlickrAPI.get_photo_info(@id))
63
70
  end
64
71
 
65
72
  def raw_sizes
66
- @raw_sizes ||= flickr.photos.getSizes :photo_id => @id
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 < OpenStruct
3
- # attrs: label, width, height, source
4
- def initialize(horrible_flickraw_response_junk)
5
- super(horrible_flickraw_response_junk.to_hash)
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 < OpenStruct
3
- # commont attrs: large large_1600 large_2048 large_square medium medium_640 medium_800 original small small_320 square thumbnail
2
+ class PhotoSizes
3
+
4
4
  def initialize(raw_sizes)
5
- super Hash[raw_sizes.map do |s|
6
- size = PhotoSize.new(s)
7
- [size.key, size]
8
- end]
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
- to_h.values.each do |value|
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
- def initialize(photoset_id)
3
+
4
+ include VerbosePuts
5
+
6
+ def initialize(photoset_id, args = {})
4
7
  @photoset_id = photoset_id
5
- ::FlickrOfflineGallery::Variables.slug = slug
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.gsub(/[^a-z0-9]/, "-").gsub(/-+/, "-")
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
- puts "Initializing photoset... " unless @photos
23
- @photos ||= info.photo.map { |raw_response| Photo.new(raw_response, @photoset_id) }.tap{ puts "Finished initializing photoset!"}
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(flickr.photosets.getPhotos(:photoset_id => @photoset_id).to_hash)
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].source
11
- local_path = photo.local_jpg_path
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
- #TODO: this is lazy, so sue me
16
- `curl --location -so "#{local_path}" "#{url}"`
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
@@ -0,0 +1,8 @@
1
+ module FlickrOfflineGallery
2
+ module VerbosePuts
3
+ def verbose_puts(string)
4
+ puts(string) if ENV["VERBOSE"]
5
+ string
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module FlickrOfflineGallery
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  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