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.
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