Created
September 9, 2012 10:32
-
-
Save suwa320/3683693 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| require 'jekyll' | |
| require 'flickraw' | |
| require 'fileutils' | |
| require 'ostruct' | |
| module Jekyll | |
| class Site | |
| attr_accessor :photostream, :photosets | |
| def site_payload | |
| {"site" => self.config.merge({ | |
| "time" => self.time, | |
| "posts" => self.posts.sort { |a, b| b <=> a }, | |
| "pages" => self.pages, | |
| "html_pages" => self.pages.reject { |page| !page.html? }, | |
| "photosets" => self.photosets, | |
| "photostream" => self.photostream, | |
| "categories" => post_attr_hash('categories'), | |
| "tags" => post_attr_hash('tags')})} | |
| end | |
| end | |
| class FlickrPhoto | |
| @@cache_dir = nil | |
| class << self | |
| def cache_dir=(dir) | |
| @@cache_dir = dir | |
| end | |
| def cache_dir | |
| @@cache_dir | |
| end | |
| end | |
| attr_accessor :title, :url, :source, :width, :height, :sizes | |
| def initialize(photo) | |
| photo = OpenStruct.new(:id => photo) if not photo.respond_to?(:id) | |
| if not cache_enable? or not load_cache(photo.id) | |
| load_photo(photo) | |
| end | |
| end | |
| def to_liquid | |
| ret = { | |
| 'title' => title, | |
| 'url' => url, | |
| 'source' => source, | |
| 'width' => width, | |
| 'height' => height | |
| } | |
| sizes.each do |k, v| | |
| ret["#{k.gsub(/ +/, '_')}_url"] = v.url | |
| ret["#{k.gsub(/ +/, '_')}_source"] = v.source | |
| ret["#{k.gsub(/ +/, '_')}_width"] = v.width | |
| ret["#{k.gsub(/ +/, '_')}_height"] = v.height | |
| end | |
| ret | |
| end | |
| private | |
| def load_photo(photo) | |
| attempt = 0 | |
| begin | |
| photo = FlickrAPI.photo_info(photo.id) if not photo.title | |
| sizes = FlickrAPI.photo_sizes(photo.id). | |
| inject({}){|h, v| h[v.label.downcase] = v; h} | |
| rescue Timeout::Error, Errno::ETIMEDOUT, Errno::ECONNRESET | |
| attempt += 1 | |
| retry if attempt < 10 | |
| end | |
| compsize = lambda {|s| | |
| (s.width.to_i >= s.height.to_i) ? | |
| (1024 - s.width.to_i).abs : (768 - s.height.to_i).abs | |
| } | |
| large = sizes.reject{|k, v| k.to_s =~ /original/i}. | |
| min{|(ak, av), (bk, bv)| compsize.call(av) <=> compsize.call(bv)}[0] | |
| @id = photo.id | |
| @title = photo.title | |
| @url = sizes[large].url | |
| @source = sizes[large].source | |
| @width = sizes[large].width | |
| @height = sizes[large].height | |
| @sizes = sizes | |
| cache if cache_enable? | |
| end | |
| def load_cache(id) | |
| cache_file = File.join(@@cache_dir, id.to_s) | |
| if File.exist?(cache_file) | |
| @id, @title, @url, @source, | |
| @width, @height, @sizes = Marshal.load(open(cache_file)) | |
| else | |
| nil | |
| end | |
| end | |
| def cache_enable? | |
| return false if not @@cache_dir | |
| FileUtils.mkdir_p(@@cache_dir) | |
| FileTest.directory?(@@cache_dir) and FileTest.writable?(@@cache_dir) | |
| end | |
| def cache | |
| open(File.join(@@cache_dir, @id.to_s), 'w') do |f| | |
| f.write(Marshal.dump([@id, @title, @url, @source, @width, @height, @sizes])) | |
| end | |
| end | |
| end | |
| class FlickrAPI | |
| class << self | |
| def setup(config) | |
| FlickRaw.api_key = config['api_key'] | |
| FlickRaw.shared_secret = config['shared_secret'] | |
| flickr.access_token = config['auth_token'] | |
| flickr.access_secret = config['secret'] | |
| FlickrPhoto.cache_dir = config['cache_dir'] | |
| end | |
| def photo_info(photo_id) | |
| flickr.photos.getInfo(:photo_id => photo_id) | |
| end | |
| def photo_sizes(photo_id) | |
| flickr.photos.getSizes(:photo_id => photo_id) | |
| end | |
| def photostream(user_id, limit = nil) | |
| page = 1 | |
| photos = [] | |
| begin | |
| response = flickr.people.getPublicPhotos( | |
| :user_id => user_id, | |
| :per_page => 500, | |
| :page => page | |
| ) | |
| photos += response.to_a | |
| page += 1 | |
| end while response['pages'].to_i >= page and | |
| ((limit and photos.size < limit) or not limit) | |
| limit ||= -1 | |
| photos = photos[0..limit].map{|v| FlickrPhoto.new(v)} | |
| end | |
| def photoset_list(user_id) | |
| page = 1 | |
| sets = [] | |
| begin | |
| response = flickr.photosets.getList( | |
| :user_id => user_id, | |
| :per_page => 500, | |
| :page => page | |
| ) | |
| sets += response.to_a | |
| page += 1 | |
| end while response['pages'].to_i >= page | |
| sets | |
| end | |
| def photoset(set_id) | |
| flickr.photosets.getInfo(:photoset_id => set_id) | |
| end | |
| def photoset_photos(set) | |
| photos = [] | |
| page = 1 | |
| begin | |
| response = flickr.photosets. | |
| getPhotos(:photoset_id => set.id) | |
| photos += response.photo | |
| page += 1 | |
| end while response['pages'].to_i >= page | |
| photos.map{|v| FlickrPhoto.new(v)} | |
| end | |
| end | |
| end | |
| class FlickrPager < Pager | |
| attr_accessor :all_posts | |
| def initialize(config, page, all_posts) | |
| config = config.dup | |
| config['paginate'] = 1 # per_page | |
| super config, page, all_posts | |
| @all_posts = all_posts | |
| end | |
| def to_liquid | |
| super.merge( | |
| 'previous_url' => (not previous_page) ? nil : | |
| File.join( | |
| all_posts[previous_page - 1].dir, | |
| all_posts[previous_page - 1].url), | |
| 'next_url' => (not next_page) ? nil : | |
| File.join( | |
| all_posts[next_page - 1].dir, | |
| all_posts[next_page - 1].url)) | |
| end | |
| end | |
| class FlickrPage < Page | |
| attr_reader :dir | |
| def initialize(site, base, dir, photos, page, title) | |
| @site = site | |
| @base = base | |
| @dir = File.join(dir, page.to_s) | |
| @name = 'index.html' | |
| self.process(@name) | |
| self.read_yaml(File.join(base, '_layouts'), 'flickr_page.html') | |
| self.data['flickr_photos'] = photos | |
| self.data['title'] = title | |
| end | |
| end | |
| class FlickrPlugin < Generator | |
| safe true | |
| priority :low | |
| def generate(site) | |
| return unless config = site.config['flickr'] | |
| FlickrAPI.setup(config) | |
| # photostream | |
| if config['photostream'] and config['user_id'] | |
| generate_photostream(site) | |
| end | |
| # photosets | |
| if config['photosets'] and config['user_id'] | |
| generate_photosets(site) | |
| end | |
| end | |
| def generate_photostream(site) | |
| config = site.config['flickr'] | |
| page = 1 | |
| per_page = config['photostream']['per_page'].to_i || 50 | |
| limit = config['photostream']['limit'].to_i || 100 | |
| photos = FlickrAPI.photostream(config['user_id'], limit) | |
| pages = limit / per_page + ((limit % per_page == 0) ? 0 : 1) | |
| dir = File.join(File::SEPARATOR, 'flickr', 'photostream') | |
| photostream_pages = [] | |
| pages.times do |i| | |
| page = i + 1 | |
| photostream_pages << FlickrPage.new( | |
| site, site.source, dir, | |
| photos[per_page * i, per_page], page, | |
| "Photostream #{(page > 1) ? "##{page}" : ""}") | |
| site.pages << photostream_pages.last | |
| site.photostream = photostream_pages.last if page == 1 | |
| end | |
| photostream_pages.each_with_index do |page, i| | |
| page.pager = FlickrPager.new(site.config, i + 1, photostream_pages) | |
| end | |
| end | |
| def generate_photosets(site) | |
| config = site.config['flickr']['photosets'] | |
| user_id = site.config['flickr']['user_id'] | |
| per_page = (config['per_page']) ? config['per_page'].to_i : 50 | |
| sets = FlickrAPI.photoset_list(user_id) | |
| site.photosets = [] | |
| sets.each do |set| | |
| photos = FlickrAPI.photoset_photos(set) | |
| pages = photos.size / per_page + | |
| ((photos.size % per_page == 0) ? 0 : 1) | |
| dir = File.join(File::SEPARATOR, 'flickr', 'photosets', set.id.to_s) | |
| set_pages = [] | |
| pages.times do |i| | |
| page = i + 1 | |
| set_pages << FlickrPage.new( | |
| site, site.source, dir, | |
| photos[per_page * i, per_page], page, | |
| "#{set.title} #{(page > 1) ? "##{page}" : ""}") | |
| site.pages << set_pages.last | |
| site.photosets << set_pages.last if page == 1 | |
| end | |
| set_pages.each_with_index do |page, i| | |
| page.pager = FlickrPager.new(site.config, i + 1, set_pages) | |
| end | |
| end | |
| end | |
| end | |
| module FlickrTag | |
| def render_tag(photos) | |
| ret = '<div class="gallery">' | |
| photos.each do |v| | |
| s = v.source | |
| i = v.sizes[@size].source | |
| w = v.sizes[@size].width | |
| h = v.sizes[@size].height | |
| ret += %{<a href="#{s}"><img src="#{i}" width="#{w}" height="#{h}" /></a>} | |
| end | |
| ret + '</div>' | |
| end | |
| end | |
| class FlickrPhotostreamTag < Liquid::Tag | |
| include FlickrTag | |
| def initialize(tag_name, text, tokens) | |
| super | |
| @size, @limit = text.strip.split(/\s+/) | |
| @size ||= 'square' | |
| @limit = @limit.to_i - 1 | |
| end | |
| def render(context) | |
| user_id = context.registers[:site].config['flickr']['user_id'] | |
| photos = FlickrAPI.photostream(user_id, @limit) | |
| render_tag(photos) | |
| end | |
| end | |
| class FlickrPhotosetTag < Liquid::Tag | |
| include FlickrTag | |
| def initialize(tag_name, text, tokens) | |
| super | |
| @set_id, @size, @limit = text.strip.split(/\s+/) | |
| @size ||= 'square' | |
| @limit = @limit.to_i - 1 | |
| end | |
| def render(context) | |
| set = FlickrAPI.photoset(@set_id) | |
| photos = FlickrAPI.photoset_photos(set) | |
| render_tag(photos[0..@limit]) | |
| end | |
| end | |
| class FlickrGalleryTag < Liquid::Block | |
| include FlickrTag | |
| def initialize(tag_name, text, tokens) | |
| super | |
| @size = text.strip | |
| @photo_ids = @nodelist.first.strip.split(/\s+/m) | |
| end | |
| def render(context) | |
| photos = @photo_ids.inject([]){|arr, v| arr << FlickrPhoto.new(v); arr} | |
| render_tag(photos) | |
| end | |
| end | |
| class FlickrLinkTag < Liquid::Tag | |
| def initialize(tag_name, text, tokens) | |
| super | |
| @photo_id, *@text = text.strip.split(/\s+/) | |
| end | |
| def render(context) | |
| photo = FlickrPhoto.new(@photo_id) | |
| <<-tag.strip | |
| <a class="flickr" href="#{photo.source}">#{@text.join(' ')}</a> | |
| tag | |
| end | |
| end | |
| end | |
| Liquid::Template.register_tag('flickr_photostream', Jekyll::FlickrPhotostreamTag) | |
| Liquid::Template.register_tag('flickr_photoset', Jekyll::FlickrPhotosetTag) | |
| Liquid::Template.register_tag('flickr_gallery', Jekyll::FlickrGalleryTag) | |
| Liquid::Template.register_tag('flickr_link', Jekyll::FlickrLinkTag) | |
| if $0 == __FILE__ | |
| puts "API Key and shared secret can be obtained at following URL" | |
| puts "http://www.flickr.com/services/apps/by/me" | |
| puts | |
| print "Your API Key: " | |
| FlickRaw.api_key = gets.strip | |
| print "Your shared secret: " | |
| FlickRaw.shared_secret = gets.strip | |
| token = flickr.get_request_token | |
| auth_url = flickr.get_authorize_url(token['oauth_token'], :perms => 'delete') | |
| puts "Open this url in your process to complete the authication process : #{auth_url}" | |
| puts "Copy here the number given when you complete the process." | |
| puts | |
| print "Number: " | |
| verify = gets.strip | |
| print "Your Username: " | |
| username = gets.strip | |
| user = flickr.people.findByUsername(:username => username) | |
| begin | |
| flickr.get_access_token( | |
| token['oauth_token'], token['oauth_token_secret'], verify) | |
| login = flickr.test.login | |
| puts "User ID: #{user['usid']}" | |
| puts "API Key: #{FlickRaw.api_key}" | |
| puts "Shared Secret: #{FlickRaw.shared_secret}" | |
| puts "Access Token: #{flickr.access_token}" | |
| puts "access_secret: #{flickr.access_secret}" | |
| rescue FlickRaw::FailedResponse => e | |
| puts "Authentication failed : #{e.msg}" | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment