I know that flickr provides APIs that allow developers to manage photos programatially in pratically any modern language. Since I am a fan of Ruby, I chose a ruby libray, flickr_fu from commontread.
So I take an hour to set up and write a ruby class to re-order my 1000+ photosets. The class name is FlickrPhotoSetSorter. Here is the step that I did and you can follow, assuming you have ruby 1.8+ installed.
1. Install flickr_fu
sudo gem install flickr-fuYou may have to install a required gem; xml-magic separately.
2. Create flickr.yml to store my flickr API key and secret key. Replace "your key" and "your secret" with the yours. You may obtain them from Flickr API keys. The token_cache.yml is a file flickr_fu uses to store your session token (flickr calls it 'frob').
## YAML Template.3. Authorize your program to read/write your albums. I defined a method, authorize, in my FlickrPhotoSetSorter class.
--- !map:Hash
key: "your key"
secret: "your secret"
token_cache: "token_cache.yml"
The method generates and displays a URL to flickr.com that you will have to visit in order to ensure that you have rights to your account. Here is an example of the result. I replaced all ids with a dummy 12345.
require 'flickr_fu'
class FlickrPhotoSetSorter
def initialize
@flickr = Flickr.new('flickr.yml')
end
def authorize
puts "visit the following url, then clickonce you have authorized:"
# request write permissions
puts @flickr.auth.url(:write)
gets
flickr.auth.cache_token
end
end
FlickrPhotoSetSorter.new.authorize
4. Once I authorized the application, I can start loading a list of my photosets using flickr_fu's Photosets class.
visit the following url, then clickonce you have authorize
http://flickr.com/services/auth/?frob=12345&auth_token=12345&api_key=12345&perms=write&api_sig=12345
def photosets_list5. Since I have a large collection of my photosets, I don't want to load them from flickr.com every time I run the script. So I chose to store the result into a file that I can load later. I created a file, list.txt and store each photoset with id, number of photos, title and description separated by a pipe symbol '|'
Flickr::Photosets.new(@flickr).get_list
end
def store_photoset_list(file_name = 'list.txt')6. To load it back, firstly I created a method to read a line and returns a hash that contain the information from a photoset.
File.open(file_name, "w") do |file|
photosets_list.map do |photoset|
file.puts("#{photoset.id}|#{photoset.num_photos}|#{photoset.title}|#{photoset.description}")
end
end
end
FlickrPhotoSetSorter.new.store_photoset_list
def photoset_from(line)
id, num_photos, title, description = line.split('|')
return nil unless id.to_i > 0
{ :id => id,
:num_photos => num_photos,
:title => title,
:description => description }
end
Then, I defined a method to load the file and build an photoset array.
def load_photoset_list(file_name = 'list.txt')7. Since flickr_fu does not have a method to sort or update the order of photosets, I have to do it by myself. It is super easy since I already have everything I need. Flickr has an API to order photo sets, flickr.photosets.orderSets and it requires a list of photoset ids separated by commas.
return @photosets_list if @photosets_list
@photosets_list = []
lines = IO.readlines(file_name)
lines.each do |line|
@photosets_list << photoset_from(line)
end
@photosets_list.compact
end
So I sort the photoset by title descending and collect ids and join them with ','. At the end, I use flickr_fu's send_request and pass the API name with the list of photoset ids using HTTP post.
def order_photosets_by_title8. To run the script, just use:
ordered_list = load_photoset_list.sort { |a,b| (b[:title] || "") <=> (a[:title] || "") }
ordered_ids = ordered_list.map { |set| set[:id] }.join(',')
@flickr.send_request('flickr.photosets.orderSets', { :photoset_ids => ordered_ids }, :post)
end
FlickrPhotoSetSorter.new.order_photosets_by_title
That's it. Now my photoset list are sorted by title descending order. I can upload older photosets, rerun the script and have them sort again and never worry that my photosets will be out of order again.
Here is the entire source code of the FlickrPhotoSetSorter class.
require 'flickr_fu'
class FlickrPhotoSetSorter
def initialize
@flickr = Flickr.new('flickr.yml')
end
def authorize
puts "visit the following url, then clickonce you have authorized:"
# request write permissions
puts @flickr.auth.url(:write)
gets
flickr.auth.cache_token
end
def photosets_list
Flickr::Photosets.new(@flickr).get_list
end
def store_photoset_list(file_name = 'list.txt')
File.open(file_name, "w") do |file|
photosets_list.map do |photoset|
file.puts("#{photoset.id}|#{photoset.num_photos}|#{photoset.title}|#{photoset.description}")
end
end
end
def load_photoset_list(file_name = 'list.txt')
return @photosets_list if @photosets_list
@photosets_list = []
lines = IO.readlines(file_name)
lines.each do |line|
@photosets_list << photoset_from(line)
end
@photosets_list.compact
end
def photoset_from(line)
id, num_photos, title, description = line.split('|')
return nil unless id.to_i > 0
{ :id => id,
:num_photos => num_photos,
:title => title,
:description => description }
end
def order_photosets_by_title
ordered_list = load_photoset_list.sort { |a,b| (b[:title] || "") <=> (a[:title] || "") }
ordered_ids = ordered_list.map { |set| set[:id] }.join(',')
@flickr.send_request('flickr.photosets.orderSets', { :photoset_ids => ordered_ids }, :post)
end
end
Feel free to use the code for you needs. If you want to reorder with different criteria, update the sort block in the order_photosets_by_title method. Rename the method as appropriate.
Enjoy.