├── .gitignore ├── examples └── example_project │ ├── __init__.py │ ├── fbconnect │ ├── __init__.py │ ├── models.py │ └── views.py │ ├── manage.py │ ├── settings.py │ ├── templates │ ├── myfriends.html │ └── welcome.html │ └── urls.py ├── readme.markdown ├── setup.py └── src └── fbpy ├── __init__.py ├── extras.py ├── facebook.py └── middleware.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.db 3 | .idea 4 | .idea/* -------------------------------------------------------------------------------- /examples/example_project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emre/fb.py/1eae613c7dd6e2a652eee312df3a9371f91be837/examples/example_project/__init__.py -------------------------------------------------------------------------------- /examples/example_project/fbconnect/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emre/fb.py/1eae613c7dd6e2a652eee312df3a9371f91be837/examples/example_project/fbconnect/__init__.py -------------------------------------------------------------------------------- /examples/example_project/fbconnect/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /examples/example_project/fbconnect/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse, HttpResponseRedirect 2 | from django.template import RequestContext 3 | from django.shortcuts import render_to_response 4 | from django.contrib.csrf.middleware import csrf_exempt 5 | 6 | from fbpy.extras import require_facebook_login 7 | 8 | @csrf_exempt 9 | def index(request): 10 | if not request.facebook.is_authenticated(): 11 | return HttpResponseRedirect(request.facebook.get_login_url()) 12 | else: 13 | user_info = request.facebook.graph().get_object("me") 14 | return render_to_response("welcome.html", user_info, context_instance = RequestContext(request)) 15 | 16 | @csrf_exempt 17 | def myfriends(request): 18 | if request.facebook.is_authenticated(): 19 | print request.facebook.auth_token 20 | friends = request.facebook.graph().get_object("me/friends") 21 | for friend in friends["data"]: 22 | friend["avatar_url"] = request.facebook.graph().get_picture(friend["id"],"small") 23 | 24 | return render_to_response("myfriends.html", {"entries": friends["data"]}, context_instance = RequestContext(request)) 25 | else: 26 | return HttpResponseRedirect(request.facebook.get_login_url()) 27 | 28 | @csrf_exempt 29 | @require_facebook_login 30 | def facebook_login_required_view(request): 31 | return HttpResponse("oo hai.") 32 | 33 | @csrf_exempt 34 | def view_with_no_access(request): 35 | user_info = request.facebook.graph().get_object("emre.py") 36 | return HttpResponse(str(user_info)) 37 | 38 | @csrf_exempt 39 | def extra_arguments_example(request): 40 | photos = request.facebook.graph().get_object("103688113031204/photos", {"limit": 5}) 41 | return HttpResponse(str(photos)) 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /examples/example_project/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from django.core.management import execute_manager 3 | try: 4 | import settings # Assumed to be in the same directory. 5 | except ImportError: 6 | import sys 7 | sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) 8 | sys.exit(1) 9 | 10 | if __name__ == "__main__": 11 | execute_manager(settings) 12 | -------------------------------------------------------------------------------- /examples/example_project/settings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | 3 | import os 4 | 5 | DEBUG = True 6 | TEMPLATE_DEBUG = DEBUG 7 | 8 | ADMINS = ( 9 | # ('Your Name', 'your_email@domain.com'), 10 | ) 11 | 12 | MANAGERS = ADMINS 13 | 14 | DATABASES = { 15 | 'default': { 16 | 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 17 | 'NAME': 'ehe.db', # Or path to database file if using sqlite3. 18 | 'USER': '', # Not used with sqlite3. 19 | 'PASSWORD': '', # Not used with sqlite3. 20 | 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 21 | 'PORT': '', # Set to empty string for default. Not used with sqlite3. 22 | } 23 | } 24 | 25 | BASE_URL = 'http://localhost:8000' 26 | BASE_PATH = os.path.realpath(os.path.dirname(__file__)) 27 | PROJECT_PATH = os.path.realpath(os.path.dirname(__file__)) 28 | MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media') 29 | 30 | # Local time zone for this installation. Choices can be found here: 31 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 32 | # although not all choices may be available on all operating systems. 33 | # On Unix systems, a value of None will cause Django to use the same 34 | # timezone as the operating system. 35 | # If running in a Windows environment this must be set to the same as your 36 | # system time zone. 37 | TIME_ZONE = 'America/Chicago' 38 | 39 | 40 | # Language code for this installation. All choices can be found here: 41 | # http://www.i18nguy.com/unicode/language-identifiers.html 42 | LANGUAGE_CODE = 'en-us' 43 | 44 | SITE_ID = 1 45 | 46 | # If you set this to False, Django will make some optimizations so as not 47 | # to load the internationalization machinery. 48 | USE_I18N = True 49 | 50 | # If you set this to False, Django will not format dates, numbers and 51 | # calendars according to the current locale 52 | USE_L10N = True 53 | 54 | # Absolute path to the directory that holds media. 55 | # Example: "/home/media/media.lawrence.com/" 56 | MEDIA_ROOT = '' 57 | 58 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a 59 | # trailing slash if there is a path component (optional in other cases). 60 | # Examples: "http://media.lawrence.com", "http://example.com/media/" 61 | MEDIA_URL = '' 62 | 63 | # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a 64 | # trailing slash. 65 | # Examples: "http://foo.com/media/", "/media/". 66 | ADMIN_MEDIA_PREFIX = '/media/' 67 | 68 | # Make this unique, and don't share it with anybody. 69 | SECRET_KEY = 'vqg*ja58-gqmfz2d=jl8cj16h6tlk$r*x66s5gfo1czwe5m+o-' 70 | 71 | # List of callables that know how to import templates from various sources. 72 | TEMPLATE_LOADERS = ( 73 | 'django.template.loaders.filesystem.Loader', 74 | 'django.template.loaders.app_directories.Loader', 75 | # 'django.template.loaders.eggs.Loader', 76 | ) 77 | 78 | MIDDLEWARE_CLASSES = ( 79 | 'django.middleware.common.CommonMiddleware', 80 | 'django.contrib.sessions.middleware.SessionMiddleware', 81 | 'django.middleware.csrf.CsrfViewMiddleware', 82 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 83 | 'django.contrib.messages.middleware.MessageMiddleware', 84 | 'fbpy.middleware.FBPYMiddleware', 85 | ) 86 | 87 | ROOT_URLCONF = 'example_project.urls' 88 | 89 | TEMPLATE_DIRS = ( 90 | "%s/templates" % BASE_PATH, 91 | ) 92 | 93 | INSTALLED_APPS = ( 94 | 'django.contrib.auth', 95 | 'django.contrib.contenttypes', 96 | 'django.contrib.sessions', 97 | 'django.contrib.sites', 98 | 'django.contrib.messages', 99 | # Uncomment the next line to enable the admin: 100 | # 'django.contrib.admin', 101 | ) 102 | 103 | FACEBOOK_CONFIG = { 104 | "redirect_uri" : "%s/fbconnect" % BASE_URL, 105 | "scope" : 'email,publish_stream,offline_access,user_hometown,user_location', 106 | "api_key" : "[fb_app_api_key]", 107 | "app_secret" : "[fb_app_secret]", 108 | "app_id" : "[fb_app_id]", 109 | } 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /examples/example_project/templates/myfriends.html: -------------------------------------------------------------------------------- 1 | {% for item in entries %} 2 |
  • 3 | {% endfor %} 4 | -------------------------------------------------------------------------------- /examples/example_project/templates/welcome.html: -------------------------------------------------------------------------------- 1 |

    2 | name: {{name}}
    3 | email: {{email}}
    4 |

    5 | 6 | 7 | 8 |
    9 | 21 | 22 | -------------------------------------------------------------------------------- /examples/example_project/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | 3 | # Uncomment the next two lines to enable the admin: 4 | # from django.contrib import admin 5 | # admin.autodiscover() 6 | 7 | from fbconnect.views import index, myfriends, facebook_login_required_view, view_with_no_access, extra_arguments_example 8 | 9 | urlpatterns = patterns('', 10 | # Example: 11 | # (r'^trailer/', include('trailer.foo.urls')), 12 | 13 | # Uncomment the admin/doc line below and add 'django.contrib.admindocs' 14 | # to INSTALLED_APPS to enable admin documentation: 15 | # (r'^admin/doc/', include('django.contrib.admindocs.urls')), 16 | 17 | # Uncomment the next line to enable the admin: 18 | # (r'^admin/', include(admin.site.urls)), 19 | url('^fbconnect/$', index, name = "index"), 20 | url('^fbconnect/myfriends$', myfriends, name = "myfriends"), 21 | url('^no_auth', view_with_no_access, name = "view_with_no_access"), 22 | url('^login_required/$', facebook_login_required_view, name = "facebook_login_required_view"), 23 | url('^extra_arguments/$', extra_arguments_example, name = "extra_arguments_example"), 24 | ) 25 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | fb.py 2 | ================= 3 | 4 | fb.py is a software development kit for Facebook. It supports both old rest api 5 | and new graph api. it uses oauth, old style signature/secretkey based api calls 6 | for old rest api are not supported at this time. 7 | 8 | you can find official documentation at facebook about api calls and methods. 9 | 10 | 1) old rest api: http://developers.facebook.com/docs/reference/rest/ 11 | 2) graph api: http://graph.facebook.com 12 | 13 | dependencies 14 | ================= 15 | 1) python-simplejson 16 | 17 | installation 18 | ================= 19 | 20 | 1) get the archive. 21 | 2) run python setup.py install (with root priviliges) 22 | 23 | usage in Django 24 | ================= 25 | 26 | 1) add these lines to your settings.py 27 | 28 | FACEBOOK_CONFIG = { 29 | "redirect_uri" : "%s/fbconnect" % BASE_URL, 30 | "scope" : 'email,publish_stream,offline_access,user_hometown,user_location', 31 | "api_key" : "[INSERT_API_KEY_HERE]", 32 | "app_secret" : "[INSERT_APPLICATION_SECRET_HERE]", 33 | "app_id" : "[INSERT_APPLICATION_ID_HERE]", 34 | } 35 | 36 | 2) add to your MIDDLEWARE_CLASSES: 37 | 38 | fbpy.middleware.FBPYMiddleware 39 | 40 | 41 | 5) after these steps, you can call FBPY instance as request.facebook. a simple view example: 42 | 43 | if not request.facebook.is_authenticated(): 44 | return HttpResponseRedirect(request.facebook.get_login_url()) 45 | else: 46 | user_info = request.facebook.graph().get_object("me") 47 | return render_to_response("welcome.html", user_info, context_instance = RequestContext(request)) 48 | 49 | 50 | 6) read the code/wait for more documentation. fb.py is one python file with inline documentation, so browsing the code is a good idea than waiting a fully documentation. 51 | 52 | installation of "example_project" 53 | ================= 54 | 55 | 1) there is a sandbox django project in example_project directory. 56 | 57 | 2) download it and edit settings.py. (FACEBOOK_CONFIG variable.) 58 | 59 | 3) run python manage.py syncdb (we need sessions!) 60 | 61 | 4) run python manage.py runserver 62 | 63 | 5) go to your web browser, and see 127.0.0.1:8000/fbconnect 64 | 65 | 66 | low level api 67 | ================= 68 | 69 | 1) in order to send calls to new graph api, a simple request should be like that: 70 | reply = request.facebook.graph().get_object("me") 71 | 72 | 2) old rest api example: (taking mutual friends for a spesific profile id) 73 | reply = request.facebook.rest().get_object("friends.getMutualFriends", target_uid = profile_id) 74 | 75 | 3) happy hacking! 76 | 77 | to-do 78 | ================= 79 | 80 | 1) more documentation. 81 | 82 | 2) handling cookie/session storage in FBPY. 83 | 84 | thanks 85 | ================= 86 | 87 | 1) Timu Eren & Yilmaz Ugurlu - suggestions and ideas. 88 | 89 | 90 | for donations: 91 | ================= 92 | 93 | Click here to lend your support to: donate for updated and new fb.py version and make a donation at www.pledgie.com ! 94 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup 4 | 5 | setup(name='fbpy', 6 | version='0.2', 7 | description='python sdk for facebook apis', 8 | author='Emre Yilmaz', 9 | author_email='mail@emreyilmaz.me', 10 | url='http://github.com/emre/fb.py', 11 | package_dir={'': 'src'}, 12 | packages = ["fbpy"] 13 | ) 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/fbpy/__init__.py: -------------------------------------------------------------------------------- 1 | from facebook import * 2 | 3 | __version__ = '0.2' 4 | -------------------------------------------------------------------------------- /src/fbpy/extras.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | 3 | from django.http import HttpResponseRedirect 4 | 5 | def require_facebook_login(function): 6 | """ 7 | login_required decorator for views. 8 | """ 9 | def wrap(request, *args, **kwargs): 10 | if not request.facebook.is_authenticated(): 11 | return HttpResponseRedirect(request.facebook.get_login_url()) 12 | return function(request, *args, **kwargs) 13 | return wrap 14 | -------------------------------------------------------------------------------- /src/fbpy/facebook.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | 3 | import urllib, simplejson 4 | 5 | """ 6 | fb.py is a python client library for facebook api. it supports both *old rest api* 7 | and *new graph api*. 8 | 9 | you can find official documentation at facebook: 10 | * old rest api: http://developers.facebook.com/docs/reference/rest/ 11 | * graph api: http://graph.facebook.com 12 | 13 | for the installation tips and usage examples, take a look to the readme. 14 | 15 | Copyright (c) 2010 emre yilmaz 16 | 17 | Permission is hereby granted, free of charge, to any person obtaining a copy 18 | of this software and associated documentation files (the "Software"), to deal 19 | in the Software without restriction, including without limitation the rights 20 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | copies of the Software, and to permit persons to whom the Software is 22 | furnished to do so, subject to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included in 25 | all copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 33 | THE SOFTWARE. 34 | 35 | """ 36 | 37 | 38 | 39 | class GraphApiException(Exception): 40 | """ 41 | custom exception class for graph api response errors. 42 | """ 43 | def __init__(self, type, message): 44 | Exception.__init__(self, message) 45 | self.type = type 46 | 47 | class RestApiException(Exception): 48 | """ 49 | custom exception class for rest api response errors. 50 | """ 51 | def __init__(self, error_code, message): 52 | Exception.__init__(self, message) 53 | self.error_code = error_code 54 | 55 | class RestApi(object): 56 | """ 57 | Facebook RestApi Backend For the FBPY. 58 | documentation for the official methods can be found at: http://developers.facebook.com/docs/reference/rest/ 59 | """ 60 | 61 | def __init__(self, token): 62 | self.auth_token = token 63 | 64 | def _handle_errors(self, api_response): 65 | """ 66 | handles api-response errors 67 | """ 68 | if isinstance(api_response, dict) and api_response.has_key("error_code"): 69 | raise RestApiException(api_response["error_code"], api_response["error_msg"]) 70 | 71 | def get_object(self, call_method, **kargs): 72 | """ 73 | @params: 74 | - call_method : method for the rest api. 75 | (http://developers.facebook.com/docs/reference/rest/) 76 | - 77 | """ 78 | return self._get_request(call_method, **kargs) 79 | 80 | def _get_request(self, call_method, **kargs): 81 | """ 82 | makes a HTTP (GET) request to the facebook rest api servers for given parameters. 83 | """ 84 | query_string = { 85 | "access_token": self.auth_token, 86 | "format": "json" 87 | } 88 | query_string.update(kargs) 89 | f = urllib.urlopen("https://api.facebook.com/method/%s?%s" % (call_method, urllib.urlencode(query_string))) 90 | api_response = simplejson.loads(f.read()) 91 | self._handle_errors(api_response) 92 | 93 | return api_response 94 | 95 | 96 | class GraphApi(object): 97 | """ 98 | Facebook GraphApi Backend For the FBPY. 99 | documentation for the official methods can be found at: https://graph.facebook.com/ 100 | """ 101 | 102 | def __init__(self, token): 103 | self.auth_token = token 104 | 105 | @property 106 | def auth_status(self): 107 | if not self.auth_token: 108 | return False 109 | 110 | return True 111 | 112 | def get_object(self, request_path, extra_params = None): 113 | """ 114 | gets the given object from facebook api. 115 | """ 116 | return self._get_request(request_path, extra_params) 117 | 118 | 119 | def put_object(self, request_path, post_data): 120 | """ 121 | puts the given object to the facebook api_key. 122 | """ 123 | return self._put_request(request_path, post_data) 124 | 125 | def _handle_errors(self, api_response): 126 | """ 127 | handles api-response errors 128 | """ 129 | if isinstance(api_response, dict) and api_response.has_key("error"): 130 | raise GraphApiException(api_response["error"]["type"], api_response["error"]["message"]) 131 | 132 | def _get_request(self, request_path, extra_params = None): 133 | """ 134 | makes a HTTP (GET) request to the facebook graph api servers for given parameters. 135 | (just for the information getter methods.) 136 | """ 137 | parameters = {} 138 | 139 | if self.auth_status: 140 | parameters.update({ 141 | "access_token" : self.auth_token, 142 | }) 143 | 144 | if extra_params: 145 | parameters.update(extra_params) 146 | 147 | f = urllib.urlopen("https://graph.facebook.com/%s?%s" % (request_path, urllib.urlencode(parameters))) 148 | 149 | api_response = simplejson.loads(f.read()) 150 | self._handle_errors(api_response) 151 | 152 | return api_response 153 | 154 | 155 | def get_picture(self, user_alias, picture_size = None): 156 | """ 157 | shortcut method to retrieve user avatars easily by selected size. 158 | possible types: small, square, large. 159 | example: 160 | - fbpy_instance.graph().get_picture(USER_ID, "small") 161 | """ 162 | extra_params = {} 163 | if user_alias == 'me': 164 | result = self.get_object("me") 165 | user_alias = result["id"] 166 | if picture_size and picture_size in ["small", "square", "large"]: 167 | extra_params.update({ 168 | "type": picture_size, 169 | }) 170 | 171 | return "https://graph.facebook.com/%s/picture?%s" % (user_alias, urllib.urlencode(extra_params)) 172 | 173 | def _put_request(self, request_path, post_data): 174 | """ 175 | makes a HTTP (POST) request to the facebook graph api servers for given parameters. 176 | (just for the information setter methods.) 177 | """ 178 | post_data.update({ 179 | "access_token": self.auth_token, 180 | }) 181 | 182 | if post_data: 183 | for key, value in post_data.iteritems(): 184 | if isinstance(value, unicode): post_data[key] = value.encode("utf8") 185 | post_data = urllib.urlencode(post_data) 186 | f = urllib.urlopen("https://graph.facebook.com/%s" % request_path, post_data) 187 | api_response = simplejson.loads(f.read()) 188 | self._handle_errors(api_response) 189 | 190 | return api_response 191 | 192 | def put_wall_post(self, user_alias, post_data): 193 | """ 194 | helper/shortcut function for wall postings 195 | @params: 196 | - user alias (profile id or username) 197 | - post_data (dictionary) 198 | - example = { 199 | "message": "foo bar", 200 | "picture": "https://github.com/images/modules/header/logov3.png", 201 | "link" : "http://www.github.com/emre/", 202 | "name" : "github logo", 203 | "description": "buraya bakarlar description alani" 204 | } 205 | if you want to post to your running user's wall, just send user_alias parameter as "me". 206 | """ 207 | return self._put_request("%s/feed" % user_alias, post_data) 208 | 209 | class FBPY(object): 210 | 211 | # config dict for usual operations 212 | CONFIG = { 213 | "scope" : None, 214 | "redirect_uri" : None, 215 | "api_key" : None, 216 | "app_id" : None, 217 | "app_secret" : None, 218 | } 219 | 220 | def __init__(self, token = None): 221 | self.auth_token = token 222 | self.graph_api_instance = None 223 | self.rest_api_instance = None 224 | self.user_id = 0 225 | 226 | def set_config(self, config): 227 | """ 228 | setter for FBPY config attribute. 229 | """ 230 | FBPY.CONFIG.update(config) 231 | 232 | def get_config(self): 233 | """ 234 | getter for FBPY config attribute. 235 | """ 236 | return FBPY.CONFIG 237 | 238 | def set_token(self, token): 239 | """ 240 | setter for FBPY oauth token. 241 | """ 242 | self.auth_token = token 243 | 244 | def set_uid(self, uid): 245 | """ 246 | setter for autenticated user id on facebook. 247 | """ 248 | self.user_id = uid 249 | 250 | def get_uid(self): 251 | """ 252 | return facebook id. 253 | """ 254 | return self.user_id 255 | 256 | def is_authenticated(self): 257 | """ 258 | returns authenticate status. 259 | """ 260 | return bool(self.auth_token) 261 | 262 | def graph(self): 263 | """ 264 | returns graph api interface 265 | """ 266 | if not self.graph_api_instance: 267 | self.graph_api_instance = GraphApi(self.auth_token) 268 | 269 | return self.graph_api_instance 270 | 271 | def rest(self): 272 | """ 273 | returns rest api interface 274 | """ 275 | if not self.rest_api_instance: 276 | self.rest_api_instance = RestApi(self.auth_token) 277 | 278 | return self.rest_api_instance 279 | 280 | @staticmethod 281 | def get_login_url(params = {}): 282 | """ 283 | gets the login url to the your facebook application 284 | @params: 285 | - api_key (if exists in FBPY.CONFIG, not required) 286 | - cancel_url (if exists in FBPY.CONFIG, not required) 287 | - next (if exists in FBPY.CONFIG, not required) 288 | - req_perms (if exists in FBPY.CONFIG, not required) 289 | """ 290 | query_string = {} 291 | 292 | # load default config 293 | query_string.update({ 294 | "client_id" : FBPY.CONFIG.get("app_id"), 295 | "redirect_uri" : FBPY.CONFIG.get("redirect_uri"), 296 | "scope" : FBPY.CONFIG.get("scope"), 297 | }) 298 | 299 | query_string.update(params) 300 | 301 | return "https://www.facebook.com/dialog/oauth?%s" % urllib.urlencode(query_string) 302 | 303 | @staticmethod 304 | def get_redirect_html(params = {}): 305 | redirect_url = FBPY.get_login_url(params) 306 | return "" % redirect_url 307 | 308 | @staticmethod 309 | def get_logout_url(params): 310 | """ 311 | gets the logout url: 312 | @params: 313 | - api_key (if exists in FBPY.CONFIG, not required) 314 | - next (if exists in FBPY.CONFIG, not required) 315 | - session_key (required) 316 | """ 317 | default_params = { 318 | "api_key": FBPY.CONFIG.get("api_key"), 319 | "next" : FBPY.CONFIG.get("logout_next_url"), 320 | } 321 | 322 | if not params.has_key("session_key"): 323 | raise Exception("session_key is required for get_logout_url method.") 324 | 325 | default_params.update(params) 326 | return "https://www.facebook.com/logout.php?%s" % urllib.urlencode(default_params) 327 | 328 | 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /src/fbpy/middleware.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf8 -*- 2 | 3 | import urllib, re, sys 4 | 5 | from fbpy import FBPY 6 | from string import split 7 | 8 | from django.conf import settings 9 | 10 | def get_token_from_facebook(code): 11 | """ 12 | gets auth token for the returned code from Facebook. 13 | """ 14 | query_string = { 15 | "client_id" : settings.FACEBOOK_CONFIG.get("app_id"), 16 | "redirect_uri" : settings.FACEBOOK_CONFIG.get("redirect_uri"), 17 | "client_secret" : settings.FACEBOOK_CONFIG.get("app_secret"), 18 | "code" : code, 19 | } 20 | content = urllib.urlopen("https://graph.facebook.com/oauth/access_token?%s" % urllib.urlencode(query_string)).read() 21 | 22 | return content 23 | 24 | class FBPYMiddleware(object): 25 | 26 | def process_request(self, request): 27 | facebook = getattr('request', 'facebook', None) 28 | if not facebook: 29 | request.facebook = FBPY() 30 | request.facebook.set_config(settings.FACEBOOK_CONFIG) 31 | if request.session.has_key("token_string"): 32 | token_string = split(request.session.get("token_string"), '&')[0] 33 | request.facebook.set_token(token_string) 34 | 35 | # if facebook returned back the user session, register it. 36 | if request.GET.has_key("code"): 37 | try: 38 | auth_response = get_token_from_facebook(request.GET.get("code")) 39 | token_string = re.search('access_token=([^&]*)', auth_response).group(1) 40 | request.facebook.set_token(token_string) 41 | # cache in session 42 | request.session["token_string"] = token_string 43 | except Exception, error: 44 | pass 45 | 46 | def process_response(self, request, response): 47 | """ 48 | internet explorer fix for iframe typed facebook applications. 49 | """ 50 | response['P3P'] = 'CP="NOI DSP COR NID ADMa OPTa OUR NOR"' 51 | return response 52 | 53 | 54 | --------------------------------------------------------------------------------