Facebook is well known social web site. For developers it offers rich API that allows making web apps integrated with the site.
Everything for developers can be found on developers.facebook.com. Available to users apps are located in apps directory. Usually users do some quizzes, publish their results and compare, comment with other friends.
Facebook app can be writen in many languages like PHP, Python, Ruby, Perl, Java. Apps are hosted on your server, not on facebook. APIs for all of this can be found on the wiki, and some support is available on the forum.
For python developers there is PyFacebook library, which helps in using the Facebook API, and in making Django apps integrated with the site. The code can be obtained from GIT repository:
git clone git://github.com/sciyoshi/pyfacebook.git
- Go to App Developers and click on Set Up New Application
- Enter a name for you app and accept the terms:
- Next we can set up icons and description for the app. You can change them later.
- After saving we will see a list of our apps. To make it available on Facebook - we have to make the app in Django.
We need a new or existing Django project. If you create a new one - set the basic configuration like database. If your done with that we can continue.
- In this app we are using FBML which is a set of extra HTML-like tags that allows easy integration with some facebook components (they can make forms, display comment boxes and so on).
- My goal is to make an app that will show some pictures from a website demotywatory.pl (you can make the same for a lolcat site for example). The basic code that extracts the URLs and info I need looks like this:
# -*- coding: utf-8 -*-
from re import findall
import urllib2
opener = urllib2.build_opener()
opener.addheaders = [('user-agent', 'Opera/9.64 (X11; Linux x86_64; U; en) Presto/2.1.1')]
d = opener.open('http://www.demotywatory.pl')
de = d.read()
print findall('<div\sclass="demot_pic"><a\shref="(.*?)"><img\ssrc="(.*?)"\sclass="demot"\salt="(.*?)"\s/></a></div>', de)
If it works I can move it to a Django view.
- I my "zalamka" test app I have one view:
# -*- coding: utf-8 -*-
from re import findall
import urllib2
from os.path import isfile, getmtime, join
from time import time
from django.http import HttpResponse
from django.shortcuts import render_to_response
from models import User
from django.conf import settings
import facebook.djangofb as facebook
@facebook.require_login()
def canvas(request):
# POST - user submitted form
if request.POST and 'demot' in request.POST and len(request.POST['demot'].strip()) > 0:
uid = request.facebook.uid
request.facebook.feed.publishUserAction ('21106...TEMPLATE_ID', {'demot' : request.POST['demot']}, [], 1)
return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
# show the images
cache_file = join(settings.MEDIA_ROOT, 'demotywator.cache')
if isfile(cache_file) and getmtime(cache_file) > time()-3600:
# use cached
de = open(cache_file).read()
else:
# get new content
try:
opener = urllib2.build_opener()
opener.addheaders = [('user-agent', 'Opera/9.64 (X11; Linux x86_64; U; en) Presto/2.1.1')]
d = opener.open('http://www.demotywatory.pl')
de = d.read()
cache = open(cache_file, 'w')
cache.write(de)
cache.close()
except:
# log this
de = ''
demots = findall('<div\sclass="demot_pic"><a\shref="(.*?)"><img\ssrc="(.*?)"\sclass="demot"\salt="(.*?)"\s/></a></div>', de)
name = request.facebook.users.getInfo([request.facebook.uid], ['first_name'])[0]['first_name']
return render_to_response('canvas.fbml', {'name': name, 'demots': demots})
Skip request.POST for now. The rest of the code is basic - get the page and extract data. For better performance I cache the data for 1 hour:
if isfile(cache_file) and getmtime(cache_file) > time()-3600:
New thing is also request.facebook which allows us to use Facebooka API mapped to Python methods.
- Used template canvas.fbml is a Django template, in which we can (but don't have to) use FBML. In my case it looks like this:
<fb:header>
It's so demotivating. <a href="http://demotywatory.pl">Demotywatory.pl</a> now on Facebook :(
</fb:header>
<style>
.demot
{
margin-top:2px;
padding:5px;
background-color:black;width:490px;margin-left:10px;
}
.demot p
{
text-align:center;
font-weight:bold;
padding-left:20px;
color:yellow;
}
</style>
<div class="clearfix" style="border: 1px #d8dfea solid; padding: 10px; width:520px;margin: 0 auto 0 auto;">
{% if demots %}
<div class="grayheader clearfix" style="text-align:center;">
{% for i in demots %}
<h3 style="margin-bottom:3px;margin-top:15px;background-color:black;color:white;padding:5px;width:490px;margin-left:10px;">{{ i.2 }}</h3>
<a href="{{ i.0 }}"><img src="{{ i.1 }}" alt="{{ i.2 }}" /></a><br />
<div class="demot"><p><img src="http://www.python.rk.edu.pl/site_media/zalamka.png" alt="" /> It's depressing, so I want to depress others</p>
<fb:editor action="./" labelwidth="100">
<input type="hidden" value="{{ i.0 }}" name="demot" />
<fb:editor-buttonset>
<fb:editor-button value="Submit"/>
</fb:editor-buttonset>
</fb:editor>
</div>
<br /><br />
{% endfor %}
</div>
{% else %}
<div class="grayheader clearfix" style="text-align:center;"><b>No pictures</b></div>
{% endif %}
<div style="text-align:center;">In this apps icons from famfamfam and Tango projects are used.</div>
</div>
FBML Tags start with fb:. In the template above I've set page header with fb:header, and made a HTML form with fb:editor (but I could use my own). In result I get:
- Displaying content isn't enough. I want to allow users post infos about a picture on their profile/wall - for this purpose I've added the form. In the view the form is controlled by this code:
if request.POST and 'demot' in request.POST and len(request.POST['demot'].strip()) > 0:
uid = request.facebook.uid
request.facebook.feed.publishUserAction ('TEMPLATE_ID', {'demot' : request.POST['demot']}, [], 1)
return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
feed.publishUserAction method takes few arg: id of registered template, dictionary with extra variable for the template, ID list of user friends to notify, and message type: 1 - one line, 2 - short.
- To publish messages on the wall we can use templates, which need to be registered on Feed Template Console:
Variables are passed in form {*name*}. Every template must start with {*actor*}, which inserts message autor name. If we use our own variables - we have to specify a test value in Sample Template Data. When we register the template we will get the template ID:
- If we have the template ID we can use it to send the message. The app ends with redirecting the user to it's wall:
request.facebook.feed.publishUserAction ('TEMPLATE ID', {'demot' : request.POST['demot']}, [], 1)
return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
The app is very simple. You can build more complex using the Facebook API, or make your website Facebook-friendly with Facebook Connect. The Facebook Connect APIs are Javascript/XFBML based and allow you to add components that allow users login using Facebook account, and comment content from your site on their walls. You can use
a middleware or
fbconnect to get cookie of a user that logged in with Facebook on your site (the Facebook login makes a cookie, which is used only by other facebook components).
For me the APIs that Facebook provie aren't the best thing on the net. One thing that there is no nice documentation for the PyFacebook (you have to look at the standard API docs). Second - if you go see an API description - there should be real code examples (expecialy for Connect), and linkt to things I could use also (for example you can add a comment on your website with XFBML or using JS API, but the docs on the JS API won't tell you that). Third: JavaScript API? JS making queries (FQL) ? It's hard to debug, hard to integrate with server-side websites. And some browsers don't render XFBML :) For me good API can be found at Flickr - clean REST API for read and write operations with various permissions that is managed by server-side language of your site.
- Added: 10.07.2009 by riklaunim