Tworzenie aplikacji Facebookowych

Wykorzystanie biblioteki PyFacebook do tworzenia aplikacji zintegrowanych pod ten serwis w Django

API Facebooka uległo zmianom i zawarty w artykule opis jest nieco przestarzały.
Facebook to potężny międzynarodowy serwis społecznościowy. Dla programistów serwis ten udostępnia usługi umożliwiające m.in.:
  • Tworzenie aplikacji "Facebookowych" - wbudowanych w serwis i mających dostęp do części danych i akcji użytkownika.
  • Tworzenie aplikacji desktopowych, aplikacji na urządzenia mobilne zintegrowanych z serwisem i jego zasobami jak aplikacje webowe wymienione powyżej.
  • Integrowanie własnych serwisów z kontami użytkowników w Facebooku poprzez Facebook Connect (logowanie, czy też np. zapraszanie znajomych).

Wszystkie materiały dostępne są na stronie developers.facebook.com. Stworzone przez programistów aplikacje możemy znaleźć w katalogu aplikacji. Typowymi aplikacjami Fb są quizy. Użytkownik wyszukuje aplikację w katalogu (lub zostaje zaproszony), przechodzi na stronę aplikacji, gdzie wyraża zgodę na udostępnienie jej części swoich danych, po czy przedstawiana mu jest zawartość. Po wypełnieniu ankiety użytkownik poznaje wynik i może go opublikować w swoim Feedzie (co np. pojawi się też jego znajomym). Znajomi mogą zacząć komentować wynik, sami wypełnić ankietę i porównywać wyniki. Podobnie jest z innymi aplikacjami (np. gry). Dobre aplikacje wciągają całe sieci użytkowników.

facbk1

Aplikacje tego typu można pisać w wielu językach skryptowych jak PHP, Python, Ruby, Perl, Java i wiele więcej. Aplikację hostujemy na własnych serwerach. Dokumentację i masę innych dokumentów znajdziemy na wiki, a pomocy szukać możemy na forum programistów. Oprócz kwestii czysto technicznych należy uwzględnić także kwestie prawne jak np. zakaz przechowywania danych zwróconych przez API Facebooka poza listą dozwolonych obiektów. Generalnie jest co czytać.

W Pythonie możemy skorzystać z biblioteki PyFacebook ułatwiającej komunikację z API Facebooka, jak i dostarczająca dodatkowe komponenty dla Django usprawniajace proces tworzenia aplikacji w tym frameworku. Kod biblioteki można pobrać z repozytorium GIT:

git clone git://github.com/sciyoshi/pyfacebook.git
Instalacja jest standardowa - setup.py install.

Zakładanie nowej aplikacji po stronie Facebooka

  • Przechodzimy na Twórcy Aplikacji i zezwalamy na jej użycie ;) I korzystamy z opcji Set Up New Application
  • Podajemy nazwę aplikacji i zgadzamy się z regulaminem:
    facbk2
  • Następnie podajemy dodatkowe informacje jak opis i ikony aplikacji. Ustawienia te można edytować w dowolnej chwili. Ustawieniami pod innymi kartami (menu z lewej) zajmiemy się późnej.
    facbk3
  • Po zapisaniu ustawień zobaczymy listę naszych aplikacji. Jak widać przykładowa aplikacja "Załamka" nie jest jeszcze opublikowana... musimy ją stworzyć!:
    facbk4

Tworzenie aplikacji w Django z pomocą PyFacebook

Jeżeli mamy już działający serwis Django w sieci - możemy dostawić do niego aplikację pod Facebooka, a jeżeli nie to tworzymy wszystko od podstaw - projekt, a po tym aplikację. Założę że mamy już stworzony i skonfigurowany projekt Django i możemy przejść do tworzenia aplikacji.
  • Aplikację tworzymy za pomocą skryptu z PyFacebook:
    python djangofb.py startapp zalamka
    Creating Facebook application 'zalamka'...
    Writing /home/piotr/svn/0skala/biblioteka/zalamka/models.py...
    Writing /home/piotr/svn/0skala/biblioteka/zalamka/views.py...
    Writing /home/piotr/svn/0skala/biblioteka/zalamka/__init__.py...
    Writing /home/piotr/svn/0skala/biblioteka/zalamka/urls.py...
    Done!
    
    There are a couple of things you NEED to do before you can use this app:
    
     * Set FACEBOOK_API_KEY and FACEBOOK_SECRET_KEY to the appropriate values in settings.py
    
     * Add 'facebook.djangofb.FacebookMiddleware' to your MIDDLEWARE_CLASSES in settings.py
    
     * Add 'NAZWA_PROJEKTU.NAZWA_APLIKACJI' to your INSTALLED_APPS in settings.py
    
    The final step is to add (r'^biblioteka/', include('biblioteka.zalamka.urls')) to your urls.py, and then set your callback page in the application settings on Facebook to 'http://your.domain.com/biblioteka/'.
    
    Good luck!
    
    Plik djangofb.py możemy skopiować do katalogu projektu z katalogu "bin" z pakietu PyFacebook. Ten skrypt tworzy szkielet aplikacji Django dla Facebooka oraz informuje co musimy jeszcze zrobić żeby ruszyć z miejsca.
  • Do settings.py dodaj zmienne FACEBOOK_API_KEY i FACEBOOK_SECRET_KEY i przypisz im wartości kluczy naszej aplikacji (dostępne na liście naszych aplikacji na Facebooku)
  • Dalej, do MIDDLEWARE_CLASSES dodajemy facebook.djangofb.FacebookMiddleware
  • I na koniec dodajemy aplikację do listy aplikacji w INSTALLED_APPS. U mnie NAZWA_PROJEKTU.zalamka
  • Teraz w urls.py dodajemy wpis dla nowej aplikacji (trochę go zmieniłem niż to co sugeruje djangofb):
    (r'^zalamka/', include('zalamka.urls'))
  • W odróżnieniu od przykładu opisanego w tutorialu PyFacebook - djangofb nie stworzyło w katalogu aplikacji podkatalogu "templates". Kopiujemy go z podkatalogu pakietu PyFacebook: /examples/pyfacebook_sample i w settings.py dodajemy do TEMPLATE_DIRS ścieżkę do tego katalogu.
  • Edytujemy plik models.py naszej aplikacji i zmieniamy maxlength na max_length (bo zapewne używamy Django 1.0 lub nowsze)
  • Tworzymy tabele aplikacji:
    python manage.py syncdb
  • Jeżeli mamy publiczne IP to możemy podpiąć lokalny serwer deweloperski do testów, jeżeli nie - musimy wrzucić aplikację na hosting i z niego debugować ;) W przypadku publicznego IP serwer deweloperski uruchamiamy na porcie 80 (standardowy port www, pod Linuksem wymagać będzie pewnie praw roota, sudo):
    python manage.py runserver 0.0.0.0:80
  • Projekt Django dostępny jest pod http://NASZE_IP, czyli aplikacja Facebookowa pod http://NASZE_IP/zalamka/.
  • Na Facebooku edytujemy ustawienia aplikacji i przechodzimy do zakładki "Strona Ramowa". Podajemy tam Canvas Callback URL czyli http://NASZE_IP/zalamka/, a także Adres URL strony ramowej - zazwyczaj nazwa aplikacji bez znaków specjalnych ("zalamka"), oraz Metoda renderowania ustawiamy na FBML.
    facbk5
  • Teraz pod adresem http://apps.facebook.com/NAZWA/ powinna być dostępna nasza aplikacja (do testów), u mnie "NAZWA", czyli "Adres URL strony ramowej" to "zalamka":
    facbk6
    facbk7
    Przykładowa zawartość nie działa (ma wbite inne URLe) więc możemy od razu przejść dalej, jeżeli "widać" aplikację na Facebooku.
  • Zamiast ramki (iframe) wybraliśmy FBML jako sposób wyświetlania aplikacji. FBML to "Facebook Markup Language", czyli zbiór dodatkowych znaczników umożliwiających integrację różnych elementów serwisu - o czy przekonamy się tworząc naszą przykładową aplikację.
  • Teraz trzeba przygotować zawartość strony głównej naszej aplikacji. W tym przykładzie chcę wyświetlać najnowsze demoty z demotywatory.pl. Kodzik który odwala brudną robotę to:
    # -*- 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)
    
    Po przetestowaniu mogę go przenieść do widoku, a wyciągnięte dane przekazać do szablonu.
  • Widok mamy jeden, views.py wygląda tak:
    # -*- 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 został zdemotywowany
    	if request.POST and 'demot' in request.POST and len(request.POST['demot'].strip()) > 0:
    		uid = request.facebook.uid
    		request.facebook.feed.publishUserAction ('21106...TUTAJ_ID_SZABLONU_WYPOWIEDZI', {'demot' : request.POST['demot']}, [], 1)
    		return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
    	
    	# wyświetl listę demotywatorów
    	
    	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})
    
    Pomińmy na razie to co jest dla request.POST. Widzimy dość prosty kod - pobieramy stronę demotywatory.pl i wyciągamy fotki. Dla większej wydajności pobraną stronę zapisujemy na serwerze i używamy przez 1 godzinę:
    if isfile(cache_file) and getmtime(cache_file) > time()-3600:
    
    Pojawia się także obiekt request.facebook, za pomocą którego mamy dostęp do API Facebooka odpowiednio opakowane w Pythonowe metody.
  • Użyty szablon canvas.fbml to zwykły szablon Django, w którym można (lecz nie trzeba) użyć znaczników FBML. Szablon wygląda tak:
    <fb:header>
     Załamka jest wszędzie. Negatywne emocje z <a href="http://demotywatory.pl">Demotywatory.pl</a> teraz na Facebooku :(
    </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="" /> To mnie zdemotywowało... niech zdemotywuje innych</p>
    	
    	<fb:editor action="./" labelwidth="100">
    	<input type="hidden" value="{{ i.0 }}" name="demot" />
    	<fb:editor-buttonset>
    		<fb:editor-button value="Udostępnij"/>
    	</fb:editor-buttonset>
    	</fb:editor>
    	
    	</div>
    	<br /><br />
    	{% endfor %}
    	</div>
    
      {% else %}
      	 <div class="grayheader clearfix" style="text-align:center;"><b>Brak demotów albo coś strasznie się zdemotywowało i nie działa</b></div>
      {% endif %}
    <div style="text-align:center;">W aplikacji wykorzystano ikony z projektów famfamfam oraz Tango.</div>
    </div>
    
    Tagi FBML rozpoznamy po fb:. W powyższym przykładzie ustawiamy nagłówek strony za pomocą fb:header, oraz generujemy formularze poprzez fb:editor (choć w tym przypadku prościej byłoby zrobić własny). W efekcie wchodząc na stronę aplikacji otrzymamy:
    facbk10
  • Wyświetlanie listy fotek to mało. W tej aplikacji chcemy żeby użytkownik mógł dodawać informacje o demotywacji do swojego profilu. Po to został umieszczony formularz w szablonie. Za jego obsługę w aplikacji odpowiada fragment widoku:
    # POST - user został zdemotywowany
    	if request.POST and 'demot' in request.POST and len(request.POST['demot'].strip()) > 0:
    		uid = request.facebook.uid
    		request.facebook.feed.publishUserAction ('TUTAJ_ID', {'demot' : request.POST['demot']}, [], 1)
    		return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
    
    Metoda feed.publishUserAction Przyjmuje kilka argumentów: id zarejestrowanego szablonu, słownik z dodatkowymi danymi jakie mają być przekazane do szablonu, lista ID znajomych, których ta wiadomość dotyczy (może być puste), oraz typ wiadomości 1 - jednolinijkowa, 2 - krótka.
  • Chcąc publikować w profilu, na feedzie użytkownika wiadomości należy zarejestrować szablon służący do tego. Można to zrobić poprzez Feed Template Console podając tekst poszczególnych typów wiadomości:
    facbk8
    Zmienne umieszczane są w postaci {*nazwa_zmiennej*}. Każda wiadomość musi zaczynać się od wbudowanej zmiennej {*actor*} wstawiającej imię, nazwisko autora wiadomości. Wstawiając własne zmienne trzeba wstawić przykładową wartość do JSONa w Sample Template Data poniżej formularza z treścią wypowiedzi. Po zarejestrowaniu dostamy numer ID szablonu:
    facbk9
  • Mając ID szablonu możemy go wykorzystać do wysłania wiadomości. Nasza aplikacja kończy się na przekierowaniu użytkownika na jego profil:
    request.facebook.feed.publishUserAction ('TUTAJ_ID', {'demot' : request.POST['demot']}, [], 1)
    return request.facebook.redirect(request.facebook.get_url('profile', id=uid))
    
    facbk11
Przedstawiona aplikacja jest bardzo prosta i wykorzystuje niewielki zakres API Facebooka. Tworzenie większych aplikacji zwiększa niestety czas potrzebny na testowanie i wykorzystywanie odpowiednich metod API. http://apps.facebook.com/zalamka/.
blog comments powered by Disqus

Kategorie

Strony