Skip to content

Commit

Permalink
initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaza committed Mar 15, 2010
0 parents commit 1306bb4
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
*.pyc
97 changes: 97 additions & 0 deletions README.txt
@@ -0,0 +1,97 @@
google_contacts
===============

Allows you to retrieve the contacts from the Gmail account of a user of your
site, via Google's APIs.

Dependencies:

- gdata-python-client
http://code.google.com/p/gdata-python-client/

- json_response
http://www.djangosnippets.org/snippets/154/
(save this snippet in a file on your PYTHONPATH called json_response.py)

- django-picklefield
http://github.com/shrubberysoft/django-picklefield
(save the fields.py file on your PYTHONPATH and rename it picklefield.py)

Installation instructions:

1. Place the google_contacts directory somewhere in your PYTHONPATH.

2. Ensure that all the dependencies (listed above) are installed.

3. Define the following variables in your project's settings.py file:

-----------------------------------------------------------------------------

GOOGLE_COOKIE_CONSENT = 'google_token_consent'

(the value can be whatever you want, as long as it's a unique cookie name
within your project)

GOOGLE_REDIRECT_SESSION_VAR = 'google_contacts_redirect'

(the value can be whatever you want, as long as it's a unique session var
within your project)

GOOGLE_REDIRECT_BASE_URL = 'http://localhost:8000'
(should be whatever the base URL of your site is)

-----------------------------------------------------------------------------

4. Use code similar to the following, in the view for which you want to
display the contact import functionality:

-----------------------------------------------------------------------------

import gdata.contacts.service

from django.conf import settings
from django.shortcuts import render_to_response
from django.template import RequestContext

from google_contacts.utils import google_get_state, google_import

def test_page(request):
request.session[settings.GOOGLE_REDIRECT_SESSION_VAR] = request.path

google_state = google_get_state(request)
gcs = gdata.contacts.service.ContactsService()
google_contacts = google_import(request, gcs, cache=True)

return render_to_response('test_page.html', {
'google_state': google_state,
'google_contacts': google_contacts
}, context_instance=RequestContext(request))

-----------------------------------------------------------------------------

5. Use code similar to the following, in the template for which you want to
display the contact import functionality:

-----------------------------------------------------------------------------

{% load google_contacts %}

<p>
{% if google_state %}
Using imported contacts from Gmail [<a
href="{% google_auth_url request %}">stop using</a>]
{% else %}
Import contacts from <a
href="{% google_auth_url request %}">Gmail</a>
{% endif %}
</p>

{% if google_contacts %}
<ul>
{% for contact in google_contacts %}
<li>{{ contact }}</li>
{% endfor %}
</ul>
{% endif %}

-----------------------------------------------------------------------------
Empty file added __init__.py
Empty file.
23 changes: 23 additions & 0 deletions models.py
@@ -0,0 +1,23 @@
from uuid import uuid4

from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.db import models

from picklefield import PickledObjectField

class ActionState(models.Model):
"""
A temporary store for the state of a user form entry.
The typical usage of this would be for an action where the user needs
to leave and return to the page, for instance in an iframe-busting
auth process.
"""
uuid = models.CharField(max_length=32, default=lambda: uuid4().hex, primary_key=True)
action_type = models.ForeignKey(ContentType, null=True)
action_id = models.PositiveIntegerField(null=True)
action = generic.GenericForeignKey('action_type', 'action_id')
data = PickledObjectField()
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
Empty file added templatetags/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions templatetags/google_contacts.py
@@ -0,0 +1,19 @@
from gdata.auth import GenerateAuthSubUrl

from django import template
from django.conf import settings
from django.core.urlresolvers import reverse

from ..utils import google_get_state

register = template.Library()

@register.simple_tag
def google_auth_url(request):
state = google_get_state(request)
if not state:
next = '%s%s' % (settings.GOOGLE_REDIRECT_BASE_URL, reverse('google_contacts_login'))
scope = 'http://www.google.com/m8/feeds/'
return GenerateAuthSubUrl(next, scope, secure=False, session=True)
else:
return reverse('google_contacts_logout')
11 changes: 11 additions & 0 deletions urls.py
@@ -0,0 +1,11 @@
from django.conf.urls.defaults import *

from views import google_get_state_token, google_login, google_logout

urlpatterns = patterns('',

url(r'^get-state-token/(?P<action_type_id>\d+)/(?P<action_id>\d+)/$', google_get_state_token, name='google_contacts_get_state_token'),
url(r'^login/$', google_login, name='google_contacts_login'),
url(r'^logout/$', google_logout, name='google_contacts_logout'),

)
52 changes: 52 additions & 0 deletions utils.py
@@ -0,0 +1,52 @@
from django.conf import settings

def google_import(request, gcs, cache=False):
"""
Uses the given contacts service object to retrieve Google Contacts and
import the entries with an email address into the contacts of the
given user.
Returns a list of 'contact name <contact@email>' strings.
"""
state = google_get_state(request)
contacts = []

if state == 'authorized':
if cache and request.session.get('google_contacts_cached'):
return request.session.get('google_contacts_cached')

gcs.SetAuthSubToken(request.session.get(settings.GOOGLE_COOKIE_CONSENT))

entries = []
feed = gcs.GetContactsFeed()
entries.extend(feed.entry)
next_link = feed.GetNextLink()
while next_link:
feed = gcs.GetContactsFeed(uri=next_link.href)
entries.extend(feed.entry)
next_link = feed.GetNextLink()

for entry in entries:
for email in entry.email:
if email.primary:
contact = '%s <%s>' % (entry.title.text, email.address)
contacts.append(contact)

if cache:
request.session['google_contacts_cached'] = contacts

return contacts


def google_get_state(request):
"""
Get the current login state for the Google Contacts API.
Possible states are:
None - logged out
authorized - logged in and consent granted
"""
state = None
if request.session.get(settings.GOOGLE_COOKIE_CONSENT):
state = 'authorized'

return state
34 changes: 34 additions & 0 deletions views.py
@@ -0,0 +1,34 @@
import gdata.contacts.service

from django.conf import settings
from django.shortcuts import redirect

from json_response import JsonResponse
from models import ActionState

def google_get_state_token(request, action_type_id, action_id):
action_state = ActionState.objects.create(**{
'action_type_id': action_type_id,
'action_id': action_id,
'data': request.GET
})
return JsonResponse({'stat': 'ok', 'token': action_state.uuid})

def google_login(request):
token_login = request.GET.get('token')

if token_login:
gcs = gdata.contacts.service.ContactsService()
gcs.SetAuthSubToken(token_login)
gcs.UpgradeToSessionToken()
request.session[settings.GOOGLE_COOKIE_CONSENT] = gcs.GetAuthSubToken()

return redirect(request.session.get(settings.GOOGLE_REDIRECT_SESSION_VAR))


def google_logout(request):
if request.session.get(settings.GOOGLE_COOKIE_CONSENT):
del request.session[settings.GOOGLE_COOKIE_CONSENT]
if request.session.get('google_contacts_cached'):
del request.session['google_contacts_cached']
return redirect(request.session.get(settings.GOOGLE_REDIRECT_SESSION_VAR))

0 comments on commit 1306bb4

Please sign in to comment.