I posted about it on Twitter this afternoon, but I finally succumbed to the FriendFeed trend and I’m going to let them do the hard work of aggregating my life stream and normalizing it. Honestly, I don’t need to fight the never-ending battle of scraping and parsing a billion feeds when a company flush with cash and smart people can do it for me, right? :)
What’s great is that they provide a fabulous API and so I took some time yesterday to build a Django application I call django-friendly that you can pop into your site to integrate everything on your FriendFeed (entries, likes, comments, media) into your own site!
friendly
to your settings.py
settings.py
called FRIENDFEED_NICKNAME
and set it to your FriendFeed username../manage.py syncdb
./manage.py feed --feeds --likes
There are a few models that implement all of the normalized fields that FriendFeed can return back to you, such as your entries, services, FriendFeed users, media, thumbnails, et cetera.
There’s a few management commands you can script to call on a regular basis to synchronize your database. Here are some possible usage cases:
This will pull the most recent 30 entries and insert any new comments, likes, entries, and so forth.
./manage.py feed --feeds
This will go back as far as it can (around 330 entries) and gather all the appropriate links and such:
./manage.py feed --feeds --all
You can get more items from other services by filtering what you pull like this. This will pull the 30 most recent Flickr entries
./manage.py feed --feeds --service flickr
This will pull all the Flickr entries it can get at:
./manage.py feed --feeds --service flickr --all
The service name you supply is a FriendFeed specified nickname for the service. They are typically pretty guessable (googlereader
, twitter
, pownce
, googletalk
, lastfm
, et cetera). The only one that might not be apparent are pure FriendFeed items which are specified using the internal
nickname.
You can pull in your liked items with the following command:
./manage.py feed --likes
All of the other arguments (–all, –service) apply for likes as well. In fact you can pull your items and likes at the same time like so:
./manage.py feed --feeds --likes --all
There are currently only two template tags for pulling FriendFeed information into your templates.
get_friendfeed_entry_list
This is a fairly complex tag; it was built to the specifications I needed for my blog here, and I think it’s fairly applicable to nearly any use case. Here’s how it works, first you’ve got the load the friendly template tags:
{% load friendly %}
Then you can call the tag like this (simple case):
{% get_friendfeed_entry_list for 'all' 30 as friendfeed_entries %}
This will pull 30 most recent entries from all services and stick the resulting list of entries into a context variable called friendfeed_entries
which you can loop over and access just like any other template variable. For example:
{% for entry in friendfeed_entries %}
<li>
<img src="{{ entry.service.iconURL}}">
<a href="{{ entry.link }}">{{ entry.title }}</a>
</li>
{% endfor %}
You can get a lot more complex. Lets say you wanted to pull any kind of entry except Flickr photos:
{% get_friendfeed_entry_list for 'all' except 'flickr' as no_flickr %}
You can even specify multiple services to exclude:
{% get_friendfeed_entry_list for 'all' except 'flickr|picasa|smugmug' as no_photos %}
As you might’ve excpected, you can do the same when you filter. You can specify only certain services to be pulled instead of all of them like so:
{% get_friendfeed_entry_list for 'lastfm|pandora' 30 as music %}
{% get_friendfeed_entry_list for 'reddit|digg|googlereader' 100 as links %}
You can use standard model methods to get the likes on an entry. For example to show a like-count:
{{ entry.num_likes }} {{ entry.num_likes|pluralize:"person,people" }} liked this.
You could alternative iterate over entry.like_set.all
to print out each like.
Currently, the process of pulling out media thumbnails is a bit ugly. I hope to write some convenience methods. This is how you have to do it now:
{% get_friendfeed_entry_list for 'flickr' 12 as flickr_photos %}
{% for photo in flickr_photos %}
<a href="{{ photo.link }}" rel="photo" class="image" title="{{ photo.title }}">
<img src="{{ photo.media_set.all.0.mediathumbnail_set.all.0.url }}">
</a>
{% endfor %}
Nasty, right?
get_friendfeed_comment_list
For any FriendFeed entry, there’s the possibility that you or others have left comments. In the case of Google Reader (and Reddit and Digg I believe) your comments on a story are imported into FriendFeed as the first comment.
You can use this tag to pull out comments by everyon or by a specific person. The specific case is what I use to filter out just my comments. You can use it like thus:
{% get_friendfeed_entry_list for 'all' as object_list %}
{% for entry in object_list %}
{% get_friendfeed_comment_list for entry.ff_id as my_comments by 'clint' %}
<dt>
<img src="{{ entry.service.iconURL }}">
<a href="{{ entry.link }}">{{ entry.title }}</a>
</dt>
{% if my_comments %}
{% for comment in my_comments %}
<dd>{{ comment.body }}</dd>
{% endfor %}
{% endif %}
{% endfor %}
You could leave out the by 'clint'
argument to get comments by all users on the entries.
I think that’s all there is right now. You can see how I’ve put all of this into action here on my site in the middle sidebar and in my Life Stream page. I paginated the results using the awesome django-pagination application.