Monday, July 28, 2008

Merging Flickr Accounts

How to Use the FlickrNet API to Merge Flickr Accounts

A few months ago, my wife finally convinced me that it doesn't make any sense to manage two separate pro Flickr accounts, and that we should transfer all the photos to one account and drop the other.

So, I looked online for tools that merge Flickr accounts, and couldn't find any. Not even on CodePlex. Don't get me wrong, I found a gazzillion mass downloaders, and uploaders and a bunch of other very cool stuff. But not a merge tool. I even contacted Flickr support, but they were totally useless.

What I really wanted was a way to download the photos from the source account, and keep all the metadata I have meticulously added to the photos over the years - titles, descriptions, sets, tags, geo tags, etc. Then, upload to the target account without disrupting the flow on my photostream. I didn't want a bunch of old photos clogging it up.

Being a developer, I decided to write my own Flickr app using the FlickrNet API library, which turned out to be fun and quite enjoyable.

I don't want to bore you with all the details of my implementation. I'd just like to point out some interesting aspects and potential pitfalls.

Getting an API Key


To get started, you'll need an API key from Flickr. Go to the Services page and click on the "Apply for an API Key" link.

The FlickrNet Library


Download the FlickrNet library from CodePlex. You can download the binaries and reference the DLL from your code. I opted for the more geeky option, and downloaded the source code, and added the FlickrNet project to my solution. This way I could step through the code and better understand how it works.

Authorizing


If you want your app to do more than merely download public photos, your users will need to authorize it. The process is quite simple, but not that obvious. You need to launch a web browser and navigate to a Url. Here's what you do to get the Url.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret);
string frob = flickr.AuthGetFrob();
string url = flickr.AuthCalcUrl(frob, FlickrNet.AuthLevel.Write);


AuthLevel can be one of the following values:
  • Read
  • Write
  • Delete
  • None

Once you have the Url, launch the default web browser.

System.Diagnostics.Process.Start(url);


At this point, the user needs to login to her account and authorize the application. Now you can retrieve the authorization token from Flickr.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret);
FlickrNet.Auth auth = flickr.AuthGetToken(frob);
string token = auth.Token;
string userName = auth.User.Username;


Downloading Photos Metadata


This is a relatively simple process. Use the PhotoSearchOptions object to define the photos you are interested in (this could be based on a user, tag, etc.). The PhotosSearch method doesn't return all the photos it finds in one call, rather it returns "pages" of photos. You use the same PhotoSearchOptions to move to the next page and bring the next batch of results.

// Get the user Id based on the user name
FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret);
FlickrNet.FoundUser user = flickr.PeopleFindByUsername(UserName);
string userId = user.UserId;

// Create a PhotoSearchOptions object
FlickrNet.PhotoSearchOptions options = new FlickrNet.PhotoSearchOptions();
options.UserId = userId;

// Retrieve the user's photos
FlickrNet.Photos photos = flickr.PhotosSearch(options);


Downloading Sets Metadata



// Get all the photosets for the user
FlickrNet.Photosets sets = flickr.PhotosetsGetList(userId);


Linking Photos to Photosets


This is where it gets a little tricky. See, Flickr allows photos to belong to 0-n sets. So, in theory I had to account for photos that are not part of any set, photos that belong to a single set, and for photos that belong to multiple sets. Since almost all of my photos belong to just one set, I've decided to cut myself some slack, and only deal with 0-1 sets per photo.

foreach (FlickrNet.Photoset set in sets.PhotosetCollection)
{
...
... //Save photoset metadata
...

// Get the photoset's photos
FlickrNet.Photoset set1 = flickr.PhotosetsGetPhotos(set.PhotosetId);
FlickrNet.Photo[] setPhotos = set1.PhotoCollection;
foreach (FlickrNet.Photo photo in setPhotos)
{
...
... // Link photo to photoset
...
}
}


Downloading Photos


The one thing to keep in mind here is that Flickr stores multiple versions of each photo (with different resolutions), so you want to make sure you download the largest one.

FlickrNet.Sizes sizes = flickr.PhotosGetSizes(photo.PhotoId);
FlickrNet.Size size = sizes.SizeCollection[sizes.SizeCollection.Length - 1];
string sourceUrl = size.Source;
string fileName = size.Source.Substring(size.Source.LastIndexOf("/") + 1);

WebClient client = new WebClient();
client.DownloadFile(sourceUrl, fileName);


Uploading Photos


Uploading the photos is easy. I just had to change the dates on the photo after the upload to make sure it shows up in the correct place in my photostream based on the upload date, and add the GEO tags, if they existed in the original metadata.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret, AuthToken);
string photoId = flickr.UploadPicture(fileName, title, description, tags, true, false, false);
flickr.PhotosSetDates(photoId, datePosted, dateTaken, FlickrNet.DateGranularity.FullDate);
flickr.PhotosGeoSetLocation(photoId, latitude, longitude);


Creating Photosets


Creating a Photoset is a breeze. Just remember to assign a primary photo to the set, and make sure the photo id is the new photo id (from the target account) not the old one.

FlickrNet.Flickr flickr = new FlickrNet.Flickr(ApiKey, SharedSecret, AuthToken);
FlickrNet.Photoset set = flickr.PhotosetsCreate(title, description, primaryPhotoId);


Now you can add the photos (already uploaded) to the newly created set.

flickr.PhotosetsAddPhoto(photosetId, photoId);


Conclusion


Working with the FlickrNet API is both easy and fun. I'm personally happy I've decided to write my own app, I think I've learned a lot from it. If you are like me, and believe that reading code makes you a better developer, I recommend downloading the source code version and using is in your solution.

Related Links


Coding4Fun
Flickr Explorer
Flickr API

13 comments:

Anonymous,  April 15, 2009 10:30 AM  

Is there any way for us laymen to merge flickr accounts?

Ron June 1, 2009 9:13 PM  

I would pay you for this app if you still have it! Really need it and I'm far from a developer.

Uri Nizan June 1, 2009 9:26 PM  

Ron,

I'd give it to you for free, but it's in such raw form I don't know if it'll work. I need a couple of weeks to work it over. When it's ready I'll post it for free.

Ellen,  July 26, 2009 12:24 PM  

I'm very interested in this as well, looking forward to your post ...

futnuh September 6, 2009 6:51 PM  

Hi Uri. If you don't have the time to work on this, I'd really appreciate if you just post the code "as is" (with an appropriate YMMV disclaimer) ...

Spellingmistakescostlives.com November 7, 2009 3:52 PM  

Great idea for an app. I'm sure many would find it useful if you manage to get it up and out there, me included!

Marten November 12, 2009 10:15 PM  

I was on the verge of building an app like yours and was wondering if you try to get 'everything' in, say, one batch or rather wanted to store the intermediate data (I have different sets, not just one) in a few tables? Just to make the process more flexible and controllable.

Anonymous,  May 13, 2010 2:27 AM  

My name is Sherry Calaway I was browsing internet and found your blog. The author did a great job. I will subscribe to your RSS feeds. Thank you for your contribution. I am a web designer myself. And here some examples of the websites that I designed for bad credit loans payday loans canada company.

Lin Fuchshuber July 14, 2010 4:13 PM  

Hello Uri, Me too, I am eager to have a merge tool like you coded. Did you have a chance to finish it? Greetings from germany, River Beach

lydia August 8, 2010 7:26 PM  

I need this too! Any updates...?

Uri Nizan August 12, 2010 2:52 PM  

To all of you who asked for the app, you can now get it form this location: http://dl.dropbox.com/u/165911/FlickrMerge.zip

Keep in mind though that you are doing it on your own risk. I am in no way liable for the consequences.

Please let me know if you would like the source code as well.

Thanks,
Uri

riverbeach August 30, 2010 11:41 PM  

Dear Uri,
I just downloaded the Seamless Flickr Tool - but unfortunately I don't understand a thing how to use it. Can you give some instructions? Whenever I start it, it says it couldn't be initialized correctly.

Thank you so much!
River

Uri Nizan August 31, 2010 4:24 PM  

How to use the tool:

Enter the user name of the source account in the text box on the right.

Sign in to the target account.

Once you authorize the application, go back to the tool and click Continue Authentication.

Then just follow the items in the Actions menu top to bottom.

Hope this helps.