2011-12-05 05:56:24 +00:00
import re
import sys
import json
2011-10-20 03:31:16 +00:00
import logging
2012-03-13 20:57:42 +00:00
import urllib
2012-03-07 19:42:16 +00:00
from datetime import timedelta
from regluit . utils . localdatetime import now , date_today
2012-01-09 20:53:09 +00:00
from random import randint
2011-12-05 05:56:24 +00:00
from re import sub
2011-12-19 06:33:13 +00:00
from itertools import islice
from decimal import Decimal as D
2011-12-23 01:34:24 +00:00
from xml . etree import ElementTree as ET
2011-10-20 03:31:16 +00:00
2011-12-19 06:33:13 +00:00
import requests
import oauth2 as oauth
2011-11-30 02:02:51 +00:00
from django import forms
2011-10-20 03:31:16 +00:00
from django . conf import settings
2011-09-12 05:53:54 +00:00
from django . contrib . auth . models import User
2011-09-27 09:27:15 +00:00
from django . core . urlresolvers import reverse
2011-10-23 18:40:06 +00:00
from django . core . exceptions import ObjectDoesNotExist
2011-12-29 01:43:52 +00:00
from django . core . mail import send_mail
2012-01-02 14:39:11 +00:00
from django . contrib import messages
2012-02-23 20:40:45 +00:00
from django . contrib . auth . decorators import login_required
2012-02-03 15:22:53 +00:00
from django . contrib . comments import Comment
2012-02-23 20:40:45 +00:00
from django . db . models import Q , Count , Sum
2011-11-01 00:26:05 +00:00
from django . forms import Select
2011-11-17 19:35:29 +00:00
from django . forms . models import modelformset_factory
2012-02-11 20:14:31 +00:00
from django . http import HttpResponseRedirect , Http404
2012-02-02 14:03:24 +00:00
from django . http import HttpResponse , HttpResponseNotFound
2011-09-29 06:23:50 +00:00
from django . views . decorators . csrf import csrf_exempt
from django . views . decorators . http import require_POST
2011-10-12 17:47:48 +00:00
from django . views . generic . edit import FormView
2011-12-01 18:17:33 +00:00
from django . views . generic . list import ListView
2011-10-25 01:29:01 +00:00
from django . views . generic . base import TemplateView
2011-09-29 01:36:47 +00:00
from django . shortcuts import render , render_to_response , get_object_or_404
2012-03-01 13:53:55 +00:00
from django . utils . http import urlencode
2011-11-22 05:28:06 +00:00
from django . utils . translation import ugettext_lazy as _
2011-10-20 03:31:16 +00:00
from regluit . core import tasks
2011-11-16 18:20:10 +00:00
from regluit . core import models , bookloader , librarything
2011-11-14 20:16:12 +00:00
from regluit . core import userlists
2011-09-29 06:23:50 +00:00
from regluit . core . search import gluejar_search
2011-10-25 01:29:01 +00:00
from regluit . core . goodreads import GoodreadsClient
2011-11-20 02:12:18 +00:00
from regluit . frontend . forms import UserData , ProfileForm , CampaignPledgeForm , GoodreadsShelfLoadingForm
2011-11-23 16:06:48 +00:00
from regluit . frontend . forms import RightsHolderForm , UserClaimForm , LibraryThingForm , OpenCampaignForm
2012-01-09 20:53:09 +00:00
from regluit . frontend . forms import ManageCampaignForm , DonateForm , CampaignAdminForm , EmailShareForm , FeedbackForm
2012-02-28 22:28:33 +00:00
from regluit . frontend . forms import EbookForm
2011-10-13 21:13:37 +00:00
from regluit . payment . manager import PaymentManager
2012-01-10 23:26:04 +00:00
from regluit . payment . models import Transaction
from regluit . payment . parameters import TARGET_TYPE_CAMPAIGN , TARGET_TYPE_DONATION , PAYMENT_TYPE_AUTHORIZATION
2012-03-23 18:28:09 +00:00
from regluit . payment . paypal import Preapproval , IPN_PAY_STATUS_NONE , IPN_PREAPPROVAL_STATUS_ACTIVE , IPN_PAY_STATUS_INCOMPLETE , IPN_PAY_STATUS_COMPLETED , IPN_PREAPPROVAL_STATUS_CANCELED , IPN_TYPE_PREAPPROVAL
2011-10-25 01:29:01 +00:00
from regluit . core import goodreads
2011-11-01 16:50:05 +00:00
from tastypie . models import ApiKey
2011-12-19 06:33:13 +00:00
from regluit . payment . models import Transaction
2011-10-25 01:29:01 +00:00
2011-10-12 17:47:48 +00:00
logger = logging . getLogger ( __name__ )
2011-10-03 16:36:04 +00:00
2012-03-08 14:36:59 +00:00
def slideshow ( max ) :
ending = models . Campaign . objects . filter ( status = ' ACTIVE ' ) . order_by ( ' deadline ' )
count = ending . count ( )
is_preview = settings . IS_PREVIEW
j = 0
if is_preview :
# on the preview site there are no active campaigns, so we should show most-wished books instead
2012-03-13 20:26:57 +00:00
worklist = models . Work . objects . order_by ( ' -num_wishes ' ) [ : max ]
2012-03-08 14:36:59 +00:00
else :
2012-03-23 15:15:37 +00:00
worklist = [ ]
if max > count :
# add all the works with active campaigns
for campaign in ending :
worklist . append ( campaign . work )
# then fill out the rest of the list with popular but inactive works
remainder = max - count
remainder_works = models . Work . objects . exclude ( campaigns__status = ' ACTIVE ' ) . order_by ( ' -num_wishes ' ) [ : remainder ]
worklist . extend ( remainder_works )
2012-03-14 13:19:06 +00:00
else :
2012-03-23 15:15:37 +00:00
# if the active campaign list has more works than we can fit
# in our slideshow, it's the only source we need to draw from
while j < max :
worklist . append ( ending [ j ] . work )
j + = 1
2012-03-08 14:36:59 +00:00
return worklist
2011-10-13 16:23:57 +00:00
2012-03-13 20:57:42 +00:00
def next ( request ) :
2012-03-23 15:15:37 +00:00
if request . COOKIES . has_key ( ' next ' ) :
response = HttpResponseRedirect ( urllib . unquote ( request . COOKIES [ ' next ' ] ) )
response . delete_cookie ( ' next ' )
return response
else :
return HttpResponseRedirect ( ' / ' )
2012-03-13 20:57:42 +00:00
2011-08-31 03:46:55 +00:00
def home ( request ) :
2011-09-27 09:27:15 +00:00
if request . user . is_authenticated ( ) :
return HttpResponseRedirect ( reverse ( ' supporter ' ,
args = [ request . user . username ] ) )
2012-01-15 23:03:54 +00:00
2012-03-08 14:36:59 +00:00
worklist = slideshow ( 12 )
works = worklist [ : 6 ]
works2 = worklist [ 6 : 12 ]
2011-12-09 00:12:26 +00:00
events = models . Wishes . objects . order_by ( ' -created ' ) [ 0 : 2 ]
return render ( request , ' home.html ' , { ' suppress_search_box ' : True , ' works ' : works , ' works2 ' : works2 , ' events ' : events } )
2011-09-12 03:44:21 +00:00
2011-11-02 19:40:43 +00:00
def stub ( request ) :
2011-11-09 17:24:26 +00:00
path = request . path [ 6 : ] # get rid of /stub/
return render ( request , ' stub.html ' , { ' path ' : path } )
2011-11-06 21:46:46 +00:00
2011-11-06 23:54:48 +00:00
def work ( request , work_id , action = ' display ' ) :
2012-02-10 03:30:33 +00:00
try :
2012-02-28 22:28:33 +00:00
work = models . Work . objects . get ( id = work_id )
2012-02-10 03:30:33 +00:00
except models . Work . DoesNotExist :
2012-02-28 22:28:33 +00:00
try :
work = models . WasWork . objects . get ( was = work_id ) . work
except models . WasWork . DoesNotExist :
raise Http404
2012-02-10 03:30:33 +00:00
2012-02-28 22:28:33 +00:00
if request . method == ' POST ' and not request . user . is_anonymous ( ) :
activetab = ' 4 '
ebook_form = EbookForm ( data = request . POST )
if ebook_form . is_valid ( ) :
ebook_form . save ( )
alert = ' Thanks for adding an ebook to unglue.it! '
else :
alert = ebook_form . errors
else :
alert = ' '
try :
activetab = request . GET [ ' tab ' ]
if activetab not in [ ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' ] :
activetab = ' 1 ' ;
except :
activetab = ' 1 ' ;
2011-12-13 02:44:35 +00:00
editions = work . editions . all ( ) . order_by ( ' -publication_date ' )
2011-11-06 22:44:50 +00:00
campaign = work . last_campaign ( )
2012-01-09 17:44:35 +00:00
try :
2012-01-31 15:07:52 +00:00
pledged = campaign . transactions ( ) . filter ( user = request . user , status = " ACTIVE " )
2012-01-09 17:44:35 +00:00
except :
2012-01-31 15:07:52 +00:00
pledged = None
2012-03-22 19:09:13 +00:00
2011-12-31 18:48:54 +00:00
try :
2012-01-17 04:28:34 +00:00
pubdate = work . publication_date [ : 4 ]
2011-12-31 18:48:54 +00:00
except IndexError :
pubdate = ' unknown '
2011-11-26 22:09:33 +00:00
if not request . user . is_anonymous ( ) :
2012-03-23 01:24:12 +00:00
claimform = UserClaimForm ( request . user , data = { ' claim-work ' : work . pk , ' claim-user ' : request . user . id } , prefix = ' claim ' )
2012-02-28 22:28:33 +00:00
for edition in editions :
#edition.ebook_form = EbookForm( data = {'user':request.user.id, 'edition':edition.pk })
2012-03-09 17:57:19 +00:00
edition . ebook_form = EbookForm ( instance = models . Ebook ( user = request . user , edition = edition , provider = ' x ' ) , prefix = ' ebook_ %d ' % edition . id )
2011-11-26 22:09:33 +00:00
else :
claimform = None
2011-11-06 22:44:50 +00:00
if campaign :
2012-03-21 21:53:33 +00:00
# pull up premiums explicitly tied to the campaign or generic premiums
2011-11-07 15:18:46 +00:00
q = Q ( campaign = campaign ) | Q ( campaign__isnull = True )
premiums = models . Premium . objects . filter ( q )
2011-11-07 20:39:02 +00:00
else :
premiums = None
2011-11-21 15:51:50 +00:00
2012-02-11 19:15:06 +00:00
wishers = work . num_wishes
2011-11-22 19:28:27 +00:00
base_url = request . build_absolute_uri ( " / " ) [ : - 1 ]
2012-02-01 20:57:03 +00:00
2012-03-23 15:09:51 +00:00
return render ( request , ' work.html ' , {
' work ' : work ,
' premiums ' : premiums ,
' ungluers ' : userlists . supporting_users ( work , 5 ) ,
' claimform ' : claimform ,
' wishers ' : wishers ,
' base_url ' : base_url ,
' editions ' : editions ,
' pubdate ' : pubdate ,
' pledged ' : pledged ,
' activetab ' : activetab ,
' alert ' : alert
} )
2011-11-21 03:23:51 +00:00
def manage_campaign ( request , id ) :
campaign = get_object_or_404 ( models . Campaign , id = id )
2011-11-26 02:23:37 +00:00
campaign . not_manager = False
campaign . problems = [ ]
2011-11-22 05:28:06 +00:00
if ( not request . user . is_authenticated ) or ( not request . user in campaign . managers . all ( ) ) :
campaign . not_manager = True
return render ( request , ' manage_campaign.html ' , { ' campaign ' : campaign } )
alerts = [ ]
if request . method == ' POST ' :
form = ManageCampaignForm ( instance = campaign , data = request . POST )
if form . is_valid ( ) :
2011-11-26 02:23:37 +00:00
form . save ( )
alerts . append ( _ ( ' Campaign data has been saved ' ) )
else :
alerts . append ( _ ( ' Campaign data has NOT been saved ' ) )
if ' launch ' in request . POST . keys ( ) :
if campaign . launchable :
2011-11-22 05:28:06 +00:00
campaign . activate ( )
alerts . append ( _ ( ' Campaign has been launched ' ) )
2011-11-26 02:23:37 +00:00
else :
2011-11-22 05:28:06 +00:00
alerts . append ( _ ( ' Campaign has NOT been launched ' ) )
else :
form = ManageCampaignForm ( instance = campaign )
2011-11-24 02:41:06 +00:00
return render ( request , ' manage_campaign.html ' , { ' campaign ' : campaign , ' form ' : form , ' problems ' : campaign . problems , ' alerts ' : alerts } )
2011-11-15 16:27:32 +00:00
2011-11-22 01:12:13 +00:00
def googlebooks ( request , googlebooks_id ) :
try :
2012-01-09 18:55:22 +00:00
edition = models . Identifier . objects . get ( type = ' goog ' , value = googlebooks_id ) . edition
except models . Identifier . DoesNotExist :
2012-01-31 15:08:43 +00:00
try :
edition = bookloader . add_by_googlebooks_id ( googlebooks_id )
if edition . new :
# add related editions asynchronously
2012-02-16 18:19:36 +00:00
tasks . populate_edition . delay ( edition . isbn_13 )
2012-01-31 15:08:43 +00:00
except bookloader . LookupFailure :
logger . warning ( " failed to load googlebooks_id %s " % googlebooks_id )
return HttpResponseNotFound ( " failed looking up googlebooks id %s " % googlebooks_id )
2011-11-22 01:12:13 +00:00
if not edition :
return HttpResponseNotFound ( " invalid googlebooks id " )
work_url = reverse ( ' work ' , kwargs = { ' work_id ' : edition . work . id } )
return HttpResponseRedirect ( work_url )
2011-10-20 03:31:16 +00:00
2011-11-15 02:13:39 +00:00
def subjects ( request ) :
order = request . GET . get ( ' order ' )
subjects = models . Subject . objects . all ( )
2011-12-19 06:33:13 +00:00
subjects = subjects . annotate ( Count ( ' works ' ) )
2011-11-15 02:13:39 +00:00
if request . GET . get ( ' order ' ) == ' count ' :
2011-12-19 06:33:13 +00:00
subjects = subjects . order_by ( ' -works__count ' )
2011-11-15 02:13:39 +00:00
else :
subjects = subjects . order_by ( ' name ' )
2011-10-20 03:31:16 +00:00
2011-11-15 02:13:39 +00:00
return render ( request , ' subjects.html ' , { ' subjects ' : subjects } )
2011-11-07 21:01:08 +00:00
2011-12-03 00:29:23 +00:00
recommended_user = User . objects . filter ( username = settings . UNGLUEIT_RECOMMENDED_USERNAME )
class WorkListView ( ListView ) :
template_name = " work_list.html "
context_object_name = " work_list "
def get_queryset ( self ) :
facet = self . kwargs [ ' facet ' ]
if ( facet == ' popular ' ) :
2012-02-11 19:15:06 +00:00
return models . Work . objects . order_by ( ' -num_wishes ' , ' id ' )
2011-12-03 00:29:23 +00:00
elif ( facet == ' recommended ' ) :
2012-03-12 20:40:21 +00:00
return models . Work . objects . filter ( wishlists__user = recommended_user ) . order_by ( ' -num_wishes ' )
2012-01-31 22:56:34 +00:00
elif ( facet == ' new ' ) :
2012-02-11 19:15:06 +00:00
return models . Work . objects . filter ( num_wishes__gt = 0 ) . order_by ( ' -created ' , ' -num_wishes ' , ' id ' )
2011-12-03 00:29:23 +00:00
else :
2012-02-01 17:43:46 +00:00
return models . Work . objects . all ( ) . order_by ( ' -created ' , ' id ' )
2011-12-03 00:29:23 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( WorkListView , self ) . get_context_data ( * * kwargs )
2011-12-03 03:31:39 +00:00
qs = self . get_queryset ( )
context [ ' ungluers ' ] = userlists . work_list_users ( qs , 5 )
context [ ' facet ' ] = self . kwargs [ ' facet ' ]
2012-02-29 18:15:38 +00:00
context [ ' works_unglued ' ] = qs . filter ( editions__ebooks__isnull = False ) . distinct ( )
2012-03-12 20:40:21 +00:00
context [ ' works_active ' ] = qs . exclude ( editions__ebooks__isnull = False ) . filter ( Q ( campaigns__status = ' ACTIVE ' ) | Q ( campaigns__status = ' SUCCESSFUL ' ) ) . distinct ( )
context [ ' works_wished ' ] = qs . exclude ( editions__ebooks__isnull = False ) . exclude ( campaigns__status = ' ACTIVE ' ) . exclude ( campaigns__status = ' SUCCESSFUL ' ) . distinct ( )
2012-02-29 18:15:38 +00:00
2012-03-02 14:40:10 +00:00
context [ ' activetab ' ] = " #3 "
2012-02-29 18:15:38 +00:00
counts = { }
counts [ ' unglued ' ] = context [ ' works_unglued ' ] . count ( )
counts [ ' unglueing ' ] = context [ ' works_active ' ] . count ( )
counts [ ' wished ' ] = context [ ' works_wished ' ] . count ( )
context [ ' counts ' ] = counts
2011-12-03 00:29:23 +00:00
return context
2012-01-15 21:48:26 +00:00
class UngluedListView ( ListView ) :
template_name = " unglued_list.html "
context_object_name = " work_list "
def work_set_counts ( self , work_set ) :
counts = { }
counts [ ' unglued ' ] = work_set . annotate ( ebook_count = Count ( ' editions__ebooks ' ) ) . filter ( ebook_count__gt = 0 ) . count ( )
return counts
def get_queryset ( self ) :
facet = self . kwargs [ ' facet ' ]
if ( facet == ' popular ' ) :
2012-02-29 19:20:50 +00:00
return models . Work . objects . filter ( editions__ebooks__isnull = False ) . distinct ( ) . order_by ( ' -num_wishes ' )
2012-01-15 21:48:26 +00:00
else :
2012-01-20 23:35:37 +00:00
#return models.Work.objects.annotate(ebook_count=Count('editions__ebooks')).filter(ebook_count__gt=0).order_by('-created')
return models . Work . objects . filter ( editions__ebooks__isnull = False ) . distinct ( ) . order_by ( ' -created ' )
2012-01-15 21:48:26 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( UngluedListView , self ) . get_context_data ( * * kwargs )
qs = self . get_queryset ( )
context [ ' counts ' ] = self . work_set_counts ( qs )
context [ ' ungluers ' ] = userlists . work_list_users ( qs , 5 )
context [ ' facet ' ] = self . kwargs [ ' facet ' ]
2012-03-02 14:40:10 +00:00
context [ ' activetab ' ] = " #1 "
2012-01-15 21:48:26 +00:00
return context
2011-12-03 00:29:23 +00:00
2011-12-01 18:17:33 +00:00
class CampaignListView ( ListView ) :
template_name = " campaign_list.html "
context_object_name = " campaign_list "
model = models . Campaign
def get_queryset ( self ) :
facet = self . kwargs [ ' facet ' ]
if ( facet == ' newest ' ) :
2011-12-06 21:37:03 +00:00
return models . Campaign . objects . filter ( status = ' ACTIVE ' ) . order_by ( ' -activated ' )
2011-12-01 22:32:53 +00:00
elif ( facet == ' pledged ' ) :
2011-12-06 21:37:03 +00:00
return models . Campaign . objects . filter ( status = ' ACTIVE ' ) . annotate ( total_pledge = Sum ( ' transaction__amount ' ) ) . order_by ( ' -total_pledge ' )
2011-12-01 22:32:53 +00:00
elif ( facet == ' pledges ' ) :
2011-12-06 21:37:03 +00:00
return models . Campaign . objects . filter ( status = ' ACTIVE ' ) . annotate ( pledges = Count ( ' transaction ' ) ) . order_by ( ' -pledges ' )
2011-12-01 18:17:33 +00:00
elif ( facet == ' almost ' ) :
2011-12-06 21:37:03 +00:00
return models . Campaign . objects . filter ( status = ' ACTIVE ' ) . all ( ) # STUB: will need to make db changes to make this work
2011-12-01 18:17:33 +00:00
elif ( facet == ' ending ' ) :
2011-12-06 21:37:03 +00:00
return models . Campaign . objects . filter ( status = ' ACTIVE ' ) . order_by ( ' deadline ' )
2011-12-01 18:17:33 +00:00
else :
return models . Campaign . objects . all ( )
2011-12-03 03:53:39 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( CampaignListView , self ) . get_context_data ( * * kwargs )
qs = self . get_queryset ( )
context [ ' ungluers ' ] = userlists . campaign_list_users ( qs , 5 )
context [ ' facet ' ] = self . kwargs [ ' facet ' ]
return context
2011-12-01 18:17:33 +00:00
2011-11-28 23:39:06 +00:00
class PledgeView ( FormView ) :
template_name = " pledge.html "
form_class = CampaignPledgeForm
embedded = False
2012-03-15 21:54:38 +00:00
def get ( self , request , * args , * * kwargs ) :
2012-03-19 23:32:37 +00:00
# change the default behavior from https://code.djangoproject.com/browser/django/tags/releases/1.3.1/django/views/generic/edit.py#L129
2012-03-15 21:54:38 +00:00
# don't automatically bind the data to the form on GET, only on POST
# compare with https://code.djangoproject.com/browser/django/tags/releases/1.3.1/django/views/generic/edit.py#L34
form_class = self . get_form_class ( )
form = form_class ( )
return self . render_to_response ( self . get_context_data ( form = form ) )
2011-11-28 23:39:06 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( PledgeView , self ) . get_context_data ( * * kwargs )
work = get_object_or_404 ( models . Work , id = self . kwargs [ " work_id " ] )
campaign = work . last_campaign ( )
2011-11-30 02:02:51 +00:00
2011-11-28 23:39:06 +00:00
if campaign :
2011-11-30 16:58:26 +00:00
premiums = campaign . effective_premiums ( )
2011-11-28 23:39:06 +00:00
2011-11-30 02:02:51 +00:00
premium_id = self . request . REQUEST . get ( ' premium_id ' , None )
preapproval_amount = self . request . REQUEST . get ( ' preapproval_amount ' , None )
2011-11-28 23:39:06 +00:00
2011-11-30 02:02:51 +00:00
if premium_id is not None and preapproval_amount is None :
2011-11-28 23:39:06 +00:00
try :
preapproval_amount = D ( models . Premium . objects . get ( id = premium_id ) . amount )
except :
preapproval_amount = None
2012-03-15 21:54:38 +00:00
2011-11-30 02:02:51 +00:00
data = { ' preapproval_amount ' : preapproval_amount , ' premium_id ' : premium_id }
2011-11-28 23:39:06 +00:00
2012-03-15 21:54:38 +00:00
form_class = self . get_form_class ( )
# no validation errors, please, when we're only doing a GET
# to avoid validation errors, don't bind the form
if preapproval_amount is not None :
form = form_class ( data )
else :
form = form_class ( )
2011-11-30 02:02:51 +00:00
2012-02-21 14:24:23 +00:00
context . update ( { ' work ' : work , ' campaign ' : campaign , ' premiums ' : premiums , ' form ' : form , ' premium_id ' : premium_id , ' faqmenu ' : ' pledge ' } )
2011-11-28 23:39:06 +00:00
return context
def form_valid ( self , form ) :
work_id = self . kwargs [ " work_id " ]
preapproval_amount = form . cleaned_data [ " preapproval_amount " ]
anonymous = form . cleaned_data [ " anonymous " ]
2012-03-21 21:53:33 +00:00
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
2011-11-28 23:39:06 +00:00
campaign = models . Work . objects . get ( id = int ( work_id ) ) . last_campaign ( )
2012-03-21 21:53:33 +00:00
premium_id = form . cleaned_data [ " premium_id " ]
# confirm that the premium_id is a valid one for the campaign in question
try :
premium = models . Premium . objects . get ( id = premium_id )
if not ( premium . campaign is None or premium . campaign == campaign ) :
premium = None
except models . Premium . DoesNotExist , e :
premium = None
2011-11-28 23:39:06 +00:00
p = PaymentManager ( embedded = self . embedded )
2012-01-04 17:03:50 +00:00
# PledgeView is wrapped in login_required -- so in theory, user should never be None -- but I'll keep this logic here for now.
2011-11-28 23:39:06 +00:00
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
user = None
if not self . embedded :
2012-01-11 01:15:39 +00:00
return_url = None
2012-01-10 20:16:04 +00:00
cancel_url = None
2011-12-19 23:34:30 +00:00
# the recipients of this authorization is not specified here but rather by the PaymentManager.
2011-12-20 19:56:01 +00:00
# set the expiry date based on the campaign deadline
2012-03-07 19:42:16 +00:00
expiry = campaign . deadline + timedelta ( days = settings . PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
2011-12-20 19:56:01 +00:00
t , url = p . authorize ( ' USD ' , TARGET_TYPE_CAMPAIGN , preapproval_amount , expiry = expiry , campaign = campaign , list = None , user = user ,
2012-03-21 21:53:33 +00:00
return_url = return_url , cancel_url = cancel_url , anonymous = anonymous , premium = premium )
2011-12-19 23:34:30 +00:00
else : # embedded view -- which we're not actively using right now.
# embedded view triggerws instant payment: send to the partnering RH
receiver_list = [ { ' email ' : settings . PAYPAL_NONPROFIT_PARTNER_EMAIL , ' amount ' : preapproval_amount } ]
2011-11-28 23:39:06 +00:00
2012-01-11 01:15:39 +00:00
return_url = None
2012-01-10 20:16:04 +00:00
cancel_url = None
2011-11-28 23:39:06 +00:00
t , url = p . pledge ( ' USD ' , TARGET_TYPE_CAMPAIGN , receiver_list , campaign = campaign , list = None , user = user ,
2012-03-21 21:53:33 +00:00
return_url = return_url , cancel_url = cancel_url , anonymous = anonymous , premium = premium )
2011-11-28 23:39:06 +00:00
if url :
logger . info ( " PledgeView paypal: " + url )
print >> sys . stderr , " CampaignFormView paypal: " , url
return HttpResponseRedirect ( url )
else :
response = t . reference
logger . info ( " PledgeView paypal: Error " + str ( t . reference ) )
return HttpResponse ( response )
2012-01-09 17:36:03 +00:00
2012-03-19 23:32:37 +00:00
class PledgeModifyView ( FormView ) :
"""
A view to handle request to change an existing pledge
"""
template_name = " pledge_modify.html "
form_class = CampaignPledgeForm
embedded = False
def get_context_data ( self , * * kwargs ) :
context = super ( PledgeModifyView , self ) . get_context_data ( * * kwargs )
# the following should be true since PledgeModifyView.as_view is wrapped in login_required
assert self . request . user . is_authenticated ( )
user = self . request . user
work = get_object_or_404 ( models . Work , id = self . kwargs [ " work_id " ] )
try :
campaign = work . last_campaign ( )
premiums = campaign . effective_premiums ( )
# which combination of campaign and transaction status required?
# Campaign must be ACTIVE
assert campaign . status == ' ACTIVE '
2012-03-23 18:28:09 +00:00
transactions = campaign . transactions ( ) . filter ( user = user , status = IPN_PREAPPROVAL_STATUS_ACTIVE )
2012-03-19 23:32:37 +00:00
assert transactions . count ( ) == 1
transaction = transactions [ 0 ]
2012-03-23 18:28:09 +00:00
assert transaction . type == PAYMENT_TYPE_AUTHORIZATION and transaction . status == IPN_PREAPPROVAL_STATUS_ACTIVE
2012-03-19 23:32:37 +00:00
except Exception , e :
raise e
# what stuff do we need to pull out to populate form?
# preapproval_amount, premium_id (which we don't have stored yet)
2012-03-21 21:53:33 +00:00
if transaction . premium is not None :
premium_id = transaction . premium . id
else :
premium_id = None
2012-03-19 23:32:37 +00:00
# is there a Transaction for an ACTIVE campaign for this
# should make sure Transaction is modifiable.
preapproval_amount = transaction . amount
data = { ' preapproval_amount ' : preapproval_amount , ' premium_id ' : premium_id }
2012-03-22 19:09:13 +00:00
# initialize form with the current state of the transaction if the current values empty
form = kwargs [ ' form ' ]
2012-03-19 23:32:37 +00:00
2012-03-22 19:09:13 +00:00
if not ( form . is_bound ) :
form_class = self . get_form_class ( )
form = form_class ( initial = data )
2012-03-19 23:32:37 +00:00
context . update ( { ' work ' : work , ' campaign ' : campaign , ' premiums ' : premiums , ' form ' : form , ' premium_id ' : premium_id , ' faqmenu ' : ' pledge ' } )
return context
2012-03-22 19:09:13 +00:00
def form_invalid ( self , form ) :
logger . info ( " form.non_field_errors: {0} " . format ( form . non_field_errors ( ) ) )
response = self . render_to_response ( self . get_context_data ( form = form ) )
return response
2012-03-19 23:32:37 +00:00
def form_valid ( self , form ) :
# What are the situations we need to deal with?
# 2 main situations: if the new amount is less than max_amount, no need to go out to PayPal again
# if new amount is greater than max_amount...need to go out and get new approval.
# to start with, we can use the standard pledge_complete, pledge_cancel machinery
# might have to modify the pledge_complete, pledge_cancel because the messages are going to be
# different because we're modifying a pledge rather than a new one.
work_id = self . kwargs [ " work_id " ]
preapproval_amount = form . cleaned_data [ " preapproval_amount " ]
anonymous = form . cleaned_data [ " anonymous " ]
assert self . request . user . is_authenticated ( )
user = self . request . user
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
campaign = models . Work . objects . get ( id = int ( work_id ) ) . last_campaign ( )
assert campaign . status == ' ACTIVE '
2012-03-21 21:53:33 +00:00
premium_id = form . cleaned_data [ " premium_id " ]
# confirm that the premium_id is a valid one for the campaign in question
try :
premium = models . Premium . objects . get ( id = premium_id )
if not ( premium . campaign is None or premium . campaign == campaign ) :
premium = None
except models . Premium . DoesNotExist , e :
premium = None
2012-03-23 18:28:09 +00:00
transactions = campaign . transactions ( ) . filter ( user = user , status = IPN_PREAPPROVAL_STATUS_ACTIVE )
2012-03-19 23:32:37 +00:00
assert transactions . count ( ) == 1
transaction = transactions [ 0 ]
2012-03-23 18:28:09 +00:00
assert transaction . type == PAYMENT_TYPE_AUTHORIZATION and transaction . status == IPN_PREAPPROVAL_STATUS_ACTIVE
2012-03-19 23:32:37 +00:00
p = PaymentManager ( embedded = self . embedded )
2012-03-21 21:53:33 +00:00
status , url = p . modify_transaction ( transaction = transaction , amount = preapproval_amount , premium = premium )
2012-03-19 23:32:37 +00:00
logger . info ( " status: {0} , url: {1} " . format ( status , url ) )
if status and url is not None :
logger . info ( " PledgeModifyView paypal: " + url )
return HttpResponseRedirect ( url )
elif status and url is None :
2012-03-20 18:21:06 +00:00
# let's use the pledge_complete template for now and maybe look into customizing it.
return HttpResponseRedirect ( " {0} ?tid= {1} " . format ( reverse ( ' pledge_complete ' ) , transaction . id ) )
2012-03-19 23:32:37 +00:00
else :
2012-03-20 18:21:06 +00:00
return HttpResponse ( " No modication made " )
2012-03-19 23:32:37 +00:00
2012-01-09 17:36:03 +00:00
class PledgeCompleteView ( TemplateView ) :
2012-01-11 01:15:39 +00:00
""" A callback for PayPal to tell unglue.it that a payment transaction has completed successfully.
Possible things to implement :
2012-03-19 23:32:37 +00:00
after pledging , supporter receives email including thanks , work pledged , amount , expiry date , any next steps they should expect ; others ?
study other confirmation emails for their contents
after pledging , supporters are returned to a thank - you screen
should have prominent " thank you " or " congratulations " message
should have prominent share options
should suggest other works for supporters to explore ( on what basis ? )
link to work page ? or to page on which supporter entered the process ? ( if the latter , how does that work with widgets ? )
should note that a confirmation email has been sent to $ email from $ sender
should briefly note next steps ( e . g . if this campaign succeeds you will be emailed on date X )
2012-01-11 01:15:39 +00:00
"""
2012-01-09 17:36:03 +00:00
template_name = " pledge_complete.html "
2012-01-10 20:16:04 +00:00
def get_context_data ( self ) :
2012-01-09 17:36:03 +00:00
# pick up all get and post parameters and display
2012-01-10 20:16:04 +00:00
context = super ( PledgeCompleteView , self ) . get_context_data ( )
2012-01-09 17:36:03 +00:00
output = " pledge complete "
output + = self . request . method + " \n " + str ( self . request . REQUEST . items ( ) )
context [ " output " ] = output
2012-01-11 01:15:39 +00:00
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
user = None
# pull out the transaction id and try to get the corresponding Transaction
transaction_id = self . request . REQUEST . get ( " tid " )
transaction = Transaction . objects . get ( id = transaction_id )
# work and campaign in question
try :
campaign = transaction . campaign
work = campaign . work
except Exception , e :
campaign = None
work = None
# we need to check whether the user tied to the transaction is indeed the authenticated user.
correct_user = False
try :
if user . id == transaction . user . id :
correct_user = True
2012-03-19 18:46:41 +00:00
else :
# should be 403 -- but let's try 404 for now -- 403 exception coming in Django 1.4
raise Http404
2012-01-11 01:15:39 +00:00
except Exception , e :
2012-03-19 18:46:41 +00:00
raise Http404
2012-01-11 01:15:39 +00:00
# check that the user had not already approved the transaction
# do we need to first run PreapprovalDetails to check on the status
# is it of type=PAYMENT_TYPE_AUTHORIZATION and status is NONE or ACTIVE (but approved is false)
2012-01-09 17:36:03 +00:00
2012-01-11 01:15:39 +00:00
if transaction . type == PAYMENT_TYPE_AUTHORIZATION :
correct_transaction_type = True
else :
correct_transaction_type = False
2012-03-16 20:03:38 +00:00
# add the work corresponding to the Transaction on the user's wishlist if it's not already on the wishlist
if user is not None and correct_user and correct_transaction_type and ( campaign is not None ) and ( work is not None ) :
# ok to overwrite Wishes.source?
user . wishlist . add_work ( work , ' pledging ' )
2012-01-11 01:15:39 +00:00
context [ " transaction " ] = transaction
context [ " correct_user " ] = correct_user
context [ " correct_transaction_type " ] = correct_transaction_type
context [ " work " ] = work
context [ " campaign " ] = campaign
2012-02-21 14:24:23 +00:00
context [ " faqmenu " ] = " complete "
2012-01-11 01:15:39 +00:00
return context
2012-01-09 17:36:03 +00:00
class PledgeCancelView ( TemplateView ) :
""" A callback for PayPal to tell unglue.it that a payment transaction has been canceled by the user """
template_name = " pledge_cancel.html "
2012-01-10 20:16:04 +00:00
def get_context_data ( self ) :
context = super ( PledgeCancelView , self ) . get_context_data ( )
2012-01-09 17:36:03 +00:00
2012-01-10 23:26:04 +00:00
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
user = None
# pull out the transaction id and try to get the corresponding Transaction
transaction_id = self . request . REQUEST . get ( " tid " )
transaction = Transaction . objects . get ( id = transaction_id )
2012-01-11 01:15:39 +00:00
# work and campaign in question
try :
campaign = transaction . campaign
work = campaign . work
except Exception , e :
campaign = None
work = None
2012-01-10 23:26:04 +00:00
# we need to check whether the user tied to the transaction is indeed the authenticated user.
correct_user = False
try :
if user . id == transaction . user . id :
correct_user = True
except Exception , e :
pass
# check that the user had not already approved the transaction
# do we need to first run PreapprovalDetails to check on the status
# is it of type=PAYMENT_TYPE_AUTHORIZATION and status is NONE or ACTIVE (but approved is false)
if transaction . type == PAYMENT_TYPE_AUTHORIZATION :
2012-01-11 01:15:39 +00:00
correct_transaction_type = True
2012-01-10 23:26:04 +00:00
else :
2012-01-11 01:15:39 +00:00
correct_transaction_type = False
2012-01-10 23:26:04 +00:00
# status?
2012-01-11 01:15:39 +00:00
2012-01-10 23:26:04 +00:00
# give the user an opportunity to approved the transaction again
# provide a URL to click on.
# https://www.sandbox.paypal.com/?cmd=_ap-preapproval&preapprovalkey=PA-6JV656290V840615H
try_again_url = ' %s ?cmd=_ap-preapproval&preapprovalkey= %s ' % ( settings . PAYPAL_PAYMENT_HOST , transaction . preapproval_key )
context [ " transaction " ] = transaction
context [ " correct_user " ] = correct_user
context [ " correct_transaction_type " ] = correct_transaction_type
context [ " try_again_url " ] = try_again_url
2012-01-11 01:15:39 +00:00
context [ " work " ] = work
context [ " campaign " ] = campaign
2012-02-21 14:24:23 +00:00
context [ " faqmenu " ] = " cancel "
2012-01-10 23:26:04 +00:00
2012-01-09 17:36:03 +00:00
return context
2011-11-28 23:39:06 +00:00
2011-12-03 00:37:27 +00:00
class DonateView ( FormView ) :
template_name = " donate.html "
form_class = DonateForm
embedded = False
#def get_context_data(self, **kwargs):
# context = super(DonateView, self).get_context_data(**kwargs)
#
# form = CampaignPledgeForm(data)
#
# context.update({'work':work,'campaign':campaign, 'premiums':premiums, 'form':form, 'premium_id':premium_id})
# return context
def form_valid ( self , form ) :
donation_amount = form . cleaned_data [ " donation_amount " ]
anonymous = form . cleaned_data [ " anonymous " ]
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
campaign = None
p = PaymentManager ( embedded = self . embedded )
# we should force login at this point -- or if no account, account creation, login, and return to this spot
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
user = None
2011-11-07 21:01:08 +00:00
2011-12-03 00:37:27 +00:00
# instant payment: send to the partnering RH
receiver_list = [ { ' email ' : settings . PAYPAL_NONPROFIT_PARTNER_EMAIL , ' amount ' : donation_amount } ]
#redirect the page back to campaign page on success
return_url = self . request . build_absolute_uri ( reverse ( ' donate ' ) )
t , url = p . pledge ( ' USD ' , TARGET_TYPE_DONATION , receiver_list , campaign = campaign , list = None , user = user ,
return_url = return_url , anonymous = anonymous )
if url :
return HttpResponseRedirect ( url )
else :
response = t . reference
logger . info ( " PledgeView paypal: Error " + str ( t . reference ) )
return HttpResponse ( response )
2011-11-16 05:22:22 +00:00
def claim ( request ) :
if request . method == ' GET ' :
data = request . GET
else :
data = request . POST
2012-03-23 01:24:12 +00:00
form = UserClaimForm ( request . user , data = data , prefix = ' claim ' )
2011-11-16 05:22:22 +00:00
if form . is_valid ( ) :
2011-11-23 16:06:48 +00:00
# make sure we're not creating a duplicate claim
2012-03-23 01:24:12 +00:00
if not models . Claim . objects . filter ( work = data [ ' claim-work ' ] , rights_holder = data [ ' claim-rights_holder ' ] , status = ' pending ' ) . count ( ) :
2011-11-16 05:22:22 +00:00
form . save ( )
2012-03-23 01:24:12 +00:00
return HttpResponseRedirect ( reverse ( ' work ' , kwargs = { ' work_id ' : data [ ' claim-work ' ] } ) )
2011-11-16 05:22:22 +00:00
else :
2012-03-23 01:24:12 +00:00
work = models . Work . objects . get ( id = data [ ' claim-work ' ] )
rights_holder = models . RightsHolder . objects . get ( id = data [ ' claim-rights_holder ' ] )
2011-11-16 05:22:22 +00:00
context = { ' form ' : form , ' work ' : work , ' rights_holder ' : rights_holder }
return render ( request , " claim.html " , context )
2011-11-20 02:12:18 +00:00
def rh_tools ( request ) :
if not request . user . is_authenticated ( ) :
return render ( request , " rh_tools.html " )
claims = request . user . claim . filter ( user = request . user )
campaign_form = " xxx "
if not claims :
return render ( request , " rh_tools.html " )
for claim in claims :
claim . campaigns = claim . work . campaigns . all ( )
claim . can_open_new = True
for campaign in claim . campaigns :
2011-11-22 05:28:06 +00:00
if campaign . status in [ ' ACTIVE ' , ' INITIALIZED ' ] :
claim . can_open_new = False
2011-11-20 02:12:18 +00:00
if claim . status == ' active ' and claim . can_open_new :
if request . method == ' POST ' and int ( request . POST [ ' work ' ] ) == claim . work . id :
claim . campaign_form = OpenCampaignForm ( request . POST )
if claim . campaign_form . is_valid ( ) :
2011-11-29 04:37:17 +00:00
new_campaign = claim . campaign_form . save ( commit = False )
2012-03-07 19:42:16 +00:00
new_campaign . deadline = date_today ( ) + timedelta ( days = int ( settings . UNGLUEIT_LONGEST_DEADLINE ) )
2011-11-29 04:37:17 +00:00
new_campaign . target = D ( settings . UNGLUEIT_MINIMUM_TARGET )
new_campaign . save ( )
claim . campaign_form . save_m2m ( )
2011-11-20 02:12:18 +00:00
claim . can_open_new = False
else :
claim . campaign_form = OpenCampaignForm ( data = { ' work ' : claim . work , ' name ' : claim . work . title , ' userid ' : request . user . id } )
else :
claim . can_open_new = False
return render ( request , " rh_tools.html " , { ' claims ' : claims , } )
2011-11-15 04:28:55 +00:00
def rh_admin ( request ) :
2011-11-19 00:50:47 +00:00
if not request . user . is_authenticated ( ) :
return render ( request , " admins_only.html " )
2011-11-21 20:08:15 +00:00
if not request . user . is_staff :
2011-11-15 04:28:55 +00:00
return render ( request , " admins_only.html " )
2011-11-17 19:35:29 +00:00
PendingFormSet = modelformset_factory ( models . Claim , fields = [ ' status ' ] , extra = 0 )
pending_data = models . Claim . objects . filter ( status = ' pending ' )
active_data = models . Claim . objects . filter ( status = ' active ' )
2011-11-15 04:28:55 +00:00
if request . method == ' POST ' :
2011-11-17 19:35:29 +00:00
if ' create_rights_holder ' in request . POST . keys ( ) :
form = RightsHolderForm ( data = request . POST )
pending_formset = PendingFormSet ( queryset = pending_data )
if form . is_valid ( ) :
form . save ( )
if ' set_claim_status ' in request . POST . keys ( ) :
pending_formset = PendingFormSet ( request . POST , request . FILES , queryset = pending_data )
form = RightsHolderForm ( )
if pending_formset . is_valid ( ) :
pending_formset . save ( )
2011-11-20 02:12:18 +00:00
pending_formset = PendingFormSet ( queryset = pending_data )
2011-11-15 04:28:55 +00:00
else :
form = RightsHolderForm ( )
2011-11-17 19:35:29 +00:00
pending_formset = PendingFormSet ( queryset = pending_data )
2011-11-15 04:28:55 +00:00
rights_holders = models . RightsHolder . objects . all ( )
2011-11-17 19:35:29 +00:00
2011-11-16 19:45:37 +00:00
context = {
' request ' : request ,
' rights_holders ' : rights_holders ,
' form ' : form ,
2011-11-17 19:35:29 +00:00
' pending ' : zip ( pending_data , pending_formset ) ,
' pending_formset ' : pending_formset ,
' active_data ' : active_data ,
2011-11-16 19:45:37 +00:00
}
2011-11-15 04:28:55 +00:00
return render ( request , " rights_holders.html " , context )
2011-12-20 22:42:06 +00:00
def campaign_admin ( request ) :
if not request . user . is_authenticated ( ) :
return render ( request , " admins_only.html " )
if not request . user . is_staff :
return render ( request , " admins_only.html " )
context = { }
2011-12-21 22:32:08 +00:00
def campaigns_types ( ) :
# pull out Campaigns with Transactions that are ACTIVE -- and hence can be executed
# Campaign.objects.filter(transaction__status='ACTIVE')
2012-03-23 18:28:09 +00:00
campaigns_with_active_transactions = models . Campaign . objects . filter ( transaction__status = IPN_PREAPPROVAL_STATUS_ACTIVE )
2011-12-21 22:32:08 +00:00
# pull out Campaigns with Transactions that are INCOMPLETE
campaigns_with_incomplete_transactions = models . Campaign . objects . filter ( transaction__status = IPN_PAY_STATUS_INCOMPLETE )
# show all Campaigns with Transactions that are COMPLETED
campaigns_with_completed_transactions = models . Campaign . objects . filter ( transaction__status = IPN_PAY_STATUS_COMPLETED )
# show Campaigns with Transactions that are CANCELED
2012-03-23 18:28:09 +00:00
campaigns_with_canceled_transactions = models . Campaign . objects . filter ( transaction__status = IPN_PREAPPROVAL_STATUS_CANCELED )
2011-12-21 22:32:08 +00:00
return ( campaigns_with_active_transactions , campaigns_with_incomplete_transactions , campaigns_with_completed_transactions ,
campaigns_with_canceled_transactions )
2011-12-20 22:42:06 +00:00
form = CampaignAdminForm ( )
2011-12-21 22:32:08 +00:00
pm = PaymentManager ( )
check_status_results = None
command_status = None
2011-12-20 22:42:06 +00:00
if request . method == ' GET ' :
2011-12-21 22:32:08 +00:00
pass
2011-12-20 22:42:06 +00:00
elif request . method == ' POST ' :
2011-12-21 22:32:08 +00:00
if ' campaign_checkstatus ' in request . POST . keys ( ) :
# campaign_checkstatus
try :
2011-12-23 01:34:24 +00:00
status = pm . checkStatus ( )
check_status_results = " "
# parse the output to display chat transaction statuses have been updated
if len ( status [ " preapprovals " ] ) :
for t in status [ " preapprovals " ] :
check_status_results + = " <p>Preapproval key: %s updated</p> " % ( t [ " key " ] )
else :
check_status_results + = " <p>No preapprovals needed updating</p> "
if len ( status [ " payments " ] ) :
for t in status [ " payments " ] :
info = " , " . join ( [ " %s : %s " % ( k , v ) for ( k , v ) in t . items ( ) ] )
check_status_results + = " <p>Payment updated: %s </p> " % ( info )
else :
check_status_results + = " <p>No payments needed updating</p> "
command_status = _ ( " Transactions updated based on PaymentDetails and PreapprovalDetails " )
2011-12-21 22:32:08 +00:00
except Exception , e :
check_status_results = e
2011-12-23 14:59:07 +00:00
elif ' execute_campaigns ' in request . POST . keys ( ) :
c_id = request . POST . get ( ' active_campaign ' , None )
if c_id is not None :
try :
campaign = models . Campaign . objects . get ( id = c_id )
results = pm . execute_campaign ( campaign )
command_status = str ( results )
except Exception , e :
command_status = " Error in executing transactions for campaign %s " % ( str ( e ) )
2011-12-21 22:32:08 +00:00
elif ' finish_campaigns ' in request . POST . keys ( ) :
2011-12-23 14:59:07 +00:00
c_id = request . POST . get ( ' incomplete_campaign ' , None )
if c_id is not None :
try :
campaign = models . Campaign . objects . get ( id = c_id )
results = pm . finish_campaign ( campaign )
command_status = str ( results )
except Exception , e :
command_status = " Error in finishing transactions for campaign %s " % ( str ( e ) )
2011-12-21 22:32:08 +00:00
elif ' cancel_campaigns ' in request . POST . keys ( ) :
2011-12-23 14:59:07 +00:00
c_id = request . POST . get ( ' active_campaign ' , None )
if c_id is not None :
try :
campaign = models . Campaign . objects . get ( id = c_id )
results = pm . cancel_campaign ( campaign )
command_status = str ( results )
except Exception , e :
command_status = " Error in canceling transactions for campaign %s " % ( str ( e ) )
2011-12-21 01:36:27 +00:00
2011-12-21 22:32:08 +00:00
( campaigns_with_active_transactions , campaigns_with_incomplete_transactions , campaigns_with_completed_transactions ,
campaigns_with_canceled_transactions ) = campaigns_types ( )
2011-12-20 22:42:06 +00:00
context . update ( {
' form ' : form ,
2011-12-21 01:36:27 +00:00
' check_status_results ' : check_status_results ,
' campaigns_with_active_transactions ' : campaigns_with_active_transactions ,
' campaigns_with_incomplete_transactions ' : campaigns_with_incomplete_transactions ,
2011-12-21 22:32:08 +00:00
' campaigns_with_completed_transactions ' : campaigns_with_completed_transactions ,
' campaigns_with_canceled_transactions ' : campaigns_with_canceled_transactions ,
' command_status ' : command_status
2011-12-20 22:42:06 +00:00
} )
2011-12-21 22:32:08 +00:00
2011-12-20 22:42:06 +00:00
return render ( request , " campaign_admin.html " , context )
2011-11-15 04:28:55 +00:00
2011-11-03 20:28:53 +00:00
def supporter ( request , supporter_username , template_name ) :
2011-10-19 07:13:29 +00:00
supporter = get_object_or_404 ( User , username = supporter_username )
wishlist = supporter . wishlist
2012-03-07 18:23:34 +00:00
works = [ ]
works2 = [ ]
works_unglued = [ ]
works_active = [ ]
works_wished = [ ]
is_preview = settings . IS_PREVIEW
2012-02-22 03:00:23 +00:00
2012-03-07 18:23:34 +00:00
if ( wishlist . works . all ( ) ) :
# querysets for tabs
# unglued tab is anything with an existing ebook
## .order_by() may clash with .distinct() and this should be fixed
works_unglued = wishlist . works . all ( ) . filter ( editions__ebooks__isnull = False ) . distinct ( ) . order_by ( ' -num_wishes ' )
# take the set complement of the unglued tab and filter it for active works to get middle tab
result = wishlist . works . all ( ) . exclude ( pk__in = works_unglued . values_list ( ' pk ' , flat = True ) )
works_active = result . filter ( Q ( campaigns__status = ' ACTIVE ' ) | Q ( campaigns__status = ' SUCCESSFUL ' ) ) . order_by ( ' -campaigns__status ' , ' campaigns__deadline ' ) . distinct ( )
# everything else goes in tab 3
works_wished = result . exclude ( pk__in = works_active . values_list ( ' pk ' , flat = True ) ) . order_by ( ' -num_wishes ' )
# badge counts
backed = works_unglued . count ( )
backing = works_active . count ( )
wished = works_wished . count ( )
2012-02-22 03:00:23 +00:00
2012-03-08 14:36:59 +00:00
else :
2012-03-07 18:23:34 +00:00
backed = 0
backing = 0
wished = 0
2012-03-08 14:36:59 +00:00
worklist = slideshow ( 8 )
works = worklist [ : 4 ]
works2 = worklist [ 4 : 8 ]
2012-02-23 20:40:45 +00:00
2011-10-19 07:13:29 +00:00
date = supporter . date_joined . strftime ( " % B %d , % Y " )
2012-02-23 20:40:45 +00:00
2011-10-23 18:40:06 +00:00
# following block to support profile admin form in supporter page
2011-10-19 07:13:29 +00:00
if request . user . is_authenticated ( ) and request . user . username == supporter_username :
2011-11-17 00:47:29 +00:00
2011-11-09 17:24:26 +00:00
try :
profile_obj = request . user . get_profile ( )
except ObjectDoesNotExist :
profile_obj = models . UserProfile ( )
profile_obj . user = request . user
2011-11-17 00:47:29 +00:00
2011-10-19 07:13:29 +00:00
if request . method == ' POST ' :
2011-10-23 18:40:06 +00:00
profile_form = ProfileForm ( data = request . POST , instance = profile_obj )
2011-10-19 07:13:29 +00:00
if profile_form . is_valid ( ) :
2012-01-24 17:36:45 +00:00
if profile_form . cleaned_data [ ' clear_facebook ' ] or profile_form . cleaned_data [ ' clear_twitter ' ] or profile_form . cleaned_data [ ' clear_goodreads ' ] :
2011-11-14 18:23:14 +00:00
if profile_form . cleaned_data [ ' clear_facebook ' ] :
profile_obj . facebook_id = 0
if profile_form . cleaned_data [ ' clear_twitter ' ] :
profile_obj . twitter_id = " "
2012-01-24 17:36:45 +00:00
if profile_form . cleaned_data [ ' clear_goodreads ' ] :
profile_obj . goodreads_user_id = None
profile_obj . goodreads_user_name = None
profile_obj . goodreads_user_link = None
profile_obj . goodreads_auth_token = None
profile_obj . goodreads_auth_secret = None
2011-11-14 18:23:14 +00:00
profile_obj . save ( )
2011-10-19 07:13:29 +00:00
profile_form . save ( )
2011-11-17 00:47:29 +00:00
2011-10-19 07:13:29 +00:00
else :
2011-11-09 17:24:26 +00:00
profile_form = ProfileForm ( instance = profile_obj )
2011-11-17 00:47:29 +00:00
if request . user . profile . goodreads_user_id is not None :
2012-01-24 17:36:45 +00:00
goodreads_id = request . user . profile . goodreads_user_id
2011-11-17 00:47:29 +00:00
else :
2012-01-24 17:36:45 +00:00
goodreads_id = None
2011-11-17 00:47:29 +00:00
if request . user . profile . librarything_id is not None :
librarything_id = request . user . profile . librarything_id
else :
librarything_id = None
2011-10-19 16:55:48 +00:00
else :
profile_form = ' '
2012-01-24 17:36:45 +00:00
goodreads_id = None
2011-11-17 00:47:29 +00:00
librarything_id = None
2011-10-19 07:13:29 +00:00
context = {
2011-10-14 14:18:38 +00:00
" supporter " : supporter ,
" wishlist " : wishlist ,
2012-02-22 03:00:23 +00:00
" works_unglued " : works_unglued ,
" works_active " : works_active ,
" works_wished " : works_wished ,
2012-03-07 18:23:34 +00:00
" works " : works ,
" works2 " : works2 ,
" is_preview " : is_preview ,
2011-10-14 14:18:38 +00:00
" backed " : backed ,
" backing " : backing ,
" wished " : wished ,
" date " : date ,
2011-10-19 07:13:29 +00:00
" profile_form " : profile_form ,
2011-11-16 20:45:33 +00:00
" ungluers " : userlists . other_users ( supporter , 5 ) ,
2011-11-17 00:47:29 +00:00
" goodreads_auth_url " : reverse ( ' goodreads_auth ' ) ,
2012-01-24 17:36:45 +00:00
" goodreads_id " : goodreads_id ,
2012-02-23 20:40:45 +00:00
" librarything_id " : librarything_id ,
2012-03-02 14:40:10 +00:00
" activetab " : " #3 "
2011-10-19 07:13:29 +00:00
}
2011-11-03 20:28:53 +00:00
return render ( request , template_name , context )
2011-10-03 16:36:04 +00:00
def edit_user ( request ) :
form = UserData ( )
if not request . user . is_authenticated ( ) :
return HttpResponseRedirect ( reverse ( ' auth_login ' ) )
oldusername = request . user . username
if request . method == ' POST ' :
# surely there's a better way to add data to the POST data?
postcopy = request . POST . copy ( )
postcopy [ ' oldusername ' ] = oldusername
form = UserData ( postcopy )
if form . is_valid ( ) : # All validation rules pass, go and change the username
request . user . username = form . cleaned_data [ ' username ' ]
request . user . save ( )
return HttpResponseRedirect ( reverse ( ' home ' ) ) # Redirect after POST
return render ( request , ' registration/user_change_form.html ' , { ' form ' : form } , )
2011-09-29 01:36:47 +00:00
def search ( request ) :
2011-09-29 01:54:50 +00:00
q = request . GET . get ( ' q ' , None )
2012-02-05 00:06:53 +00:00
page = int ( request . GET . get ( ' page ' , 1 ) )
results = gluejar_search ( q , user_ip = request . META [ ' REMOTE_ADDR ' ] , page = page )
2011-09-29 06:23:50 +00:00
2011-10-10 22:08:53 +00:00
# flag search result as on wishlist as appropriate
2011-09-30 01:01:28 +00:00
if not request . user . is_anonymous ( ) :
2011-11-14 20:40:33 +00:00
ungluers = userlists . other_users ( request . user , 5 )
else :
2011-11-15 16:47:47 +00:00
ungluers = userlists . other_users ( None , 5 )
2012-02-05 00:06:53 +00:00
2012-01-03 00:07:12 +00:00
works = [ ]
2011-11-15 16:27:32 +00:00
for result in results :
2012-01-31 15:07:52 +00:00
try :
work = models . Identifier . objects . get ( type = ' goog ' , value = result [ ' googlebooks_id ' ] ) . work
works . append ( work )
except models . Identifier . DoesNotExist :
works . append ( result )
2011-09-29 01:54:50 +00:00
context = {
" q " : q ,
2012-01-03 00:07:12 +00:00
" results " : works ,
2011-11-14 20:40:33 +00:00
" ungluers " : ungluers
2011-09-29 01:54:50 +00:00
}
return render ( request , ' search.html ' , context )
2011-09-29 06:23:50 +00:00
2011-09-29 11:44:03 +00:00
# TODO: perhaps this functionality belongs in the API?
2011-09-29 06:23:50 +00:00
@require_POST
@login_required
2011-10-10 16:57:10 +00:00
@csrf_exempt
2011-09-29 06:23:50 +00:00
def wishlist ( request ) :
2011-10-10 16:57:10 +00:00
googlebooks_id = request . POST . get ( ' googlebooks_id ' , None )
2011-09-29 11:44:03 +00:00
remove_work_id = request . POST . get ( ' remove_work_id ' , None )
2011-12-28 02:39:40 +00:00
add_work_id = request . POST . get ( ' add_work_id ' , None )
2012-01-31 23:15:03 +00:00
2011-10-10 16:57:10 +00:00
if googlebooks_id :
2012-01-31 19:54:48 +00:00
try :
edition = bookloader . add_by_googlebooks_id ( googlebooks_id )
if edition . new :
# add related editions asynchronously
2012-02-16 18:19:36 +00:00
tasks . populate_edition . delay ( edition . isbn_13 )
2012-01-31 19:54:48 +00:00
request . user . wishlist . add_work ( edition . work , ' user ' )
except bookloader . LookupFailure :
logger . warning ( " failed to load googlebooks_id %s " % googlebooks_id )
except Exception , e :
logger . warning ( " Error in wishlist adding %s " % ( e ) )
2011-09-29 11:44:03 +00:00
# TODO: redirect to work page, when it exists
return HttpResponseRedirect ( ' / ' )
elif remove_work_id :
2012-03-09 21:05:01 +00:00
try :
work = models . Work . objects . get ( id = int ( remove_work_id ) )
except models . Work . DoesNotExist :
try :
work = models . WasWork . objects . get ( was = work_id ) . work
except models . WasWork . DoesNotExist :
raise Http404
2011-12-08 23:22:05 +00:00
request . user . wishlist . remove_work ( work )
2011-09-29 16:42:19 +00:00
# TODO: where to redirect?
2011-09-29 11:44:03 +00:00
return HttpResponseRedirect ( ' / ' )
2011-12-28 02:39:40 +00:00
elif add_work_id :
2011-12-31 18:49:23 +00:00
# if adding from work page, we have may work.id, not googlebooks_id
2012-03-09 21:05:01 +00:00
try :
work = models . Work . objects . get ( pk = add_work_id )
except models . Work . DoesNotExist :
try :
work = models . WasWork . objects . get ( was = work_id ) . work
except models . WasWork . DoesNotExist :
raise Http404
2011-12-31 18:49:23 +00:00
request . user . wishlist . add_work ( work , ' user ' )
2011-12-28 02:39:40 +00:00
return HttpResponseRedirect ( ' / ' )
2011-10-14 02:16:28 +00:00
2011-10-12 17:47:48 +00:00
class CampaignFormView ( FormView ) :
template_name = " campaign_detail.html "
form_class = CampaignPledgeForm
2011-11-23 21:14:39 +00:00
embedded = False
2011-10-12 17:47:48 +00:00
def get_context_data ( self , * * kwargs ) :
pk = self . kwargs [ " pk " ]
campaign = models . Campaign . objects . get ( id = int ( pk ) )
context = super ( CampaignFormView , self ) . get_context_data ( * * kwargs )
2011-11-22 02:06:44 +00:00
base_url = self . request . build_absolute_uri ( " / " ) [ : - 1 ]
2011-10-12 17:47:48 +00:00
context . update ( {
2011-11-22 11:14:58 +00:00
' embedded ' : self . embedded ,
2011-11-22 02:06:44 +00:00
' campaign ' : campaign ,
' base_url ' : base_url
2011-10-13 21:13:37 +00:00
} )
2011-11-22 02:06:44 +00:00
2011-10-13 21:13:37 +00:00
return context
2011-10-20 03:31:16 +00:00
2011-10-13 21:13:37 +00:00
def form_valid ( self , form ) :
pk = self . kwargs [ " pk " ]
2011-10-18 23:27:20 +00:00
preapproval_amount = form . cleaned_data [ " preapproval_amount " ]
2011-11-01 21:08:09 +00:00
anonymous = form . cleaned_data [ " anonymous " ]
2011-10-18 23:27:20 +00:00
# right now, if there is a non-zero pledge amount, go with that. otherwise, do the pre_approval
2011-10-13 21:13:37 +00:00
campaign = models . Campaign . objects . get ( id = int ( pk ) )
2011-11-22 11:14:58 +00:00
p = PaymentManager ( embedded = self . embedded )
2011-10-13 21:13:37 +00:00
2011-10-18 23:27:20 +00:00
# we should force login at this point -- or if no account, account creation, login, and return to this spot
2011-10-13 21:13:37 +00:00
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
user = None
2011-10-18 23:27:20 +00:00
2011-11-09 18:05:03 +00:00
# calculate the work corresponding to the campaign id
work_id = campaign . work . id
2011-11-22 11:14:58 +00:00
2011-12-20 19:56:01 +00:00
# set the expiry date based on the campaign deadline
2012-03-07 19:42:16 +00:00
expiry = campaign . deadline + timedelta ( days = settings . PREAPPROVAL_PERIOD_AFTER_CAMPAIGN )
2011-12-20 19:56:01 +00:00
2011-11-22 11:14:58 +00:00
if not self . embedded :
return_url = self . request . build_absolute_uri ( reverse ( ' work ' , kwargs = { ' work_id ' : str ( work_id ) } ) )
2011-12-20 19:56:01 +00:00
t , url = p . authorize ( ' USD ' , TARGET_TYPE_CAMPAIGN , preapproval_amount , expiry = expiry , campaign = campaign , list = None , user = user ,
2011-11-09 18:05:03 +00:00
return_url = return_url , anonymous = anonymous )
2011-11-22 11:14:58 +00:00
else :
# instant payment: send to the partnering RH
# right now, all money going to Gluejar.
receiver_list = [ { ' email ' : settings . PAYPAL_GLUEJAR_EMAIL , ' amount ' : preapproval_amount } ]
#redirect the page back to campaign page on success
return_url = self . request . build_absolute_uri ( reverse ( ' campaign_by_id ' , kwargs = { ' pk ' : str ( pk ) } ) )
t , url = p . pledge ( ' USD ' , TARGET_TYPE_CAMPAIGN , receiver_list , campaign = campaign , list = None , user = user ,
return_url = return_url , anonymous = anonymous )
2011-10-13 21:13:37 +00:00
if url :
2011-10-14 02:16:28 +00:00
logger . info ( " CampaignFormView paypal: " + url )
2011-11-23 18:50:29 +00:00
print >> sys . stderr , " CampaignFormView paypal: " , url
2011-10-13 21:13:37 +00:00
return HttpResponseRedirect ( url )
else :
response = t . reference
2011-10-14 02:16:28 +00:00
logger . info ( " CampaignFormView paypal: Error " + str ( t . reference ) )
2011-10-14 14:42:33 +00:00
return HttpResponse ( response )
2011-10-25 01:29:01 +00:00
2012-03-08 03:06:30 +00:00
class InfoPageView ( TemplateView ) :
def get_template_names ( self , * * kwargs ) :
if self . kwargs [ ' template_name ' ] :
return ( self . kwargs [ ' template_name ' ] )
else :
return ( ' metrics.html ' )
def get_context_data ( self , * * kwargs ) :
users = User . objects
2012-03-07 19:42:16 +00:00
users . today = users . filter ( date_joined__range = ( date_today ( ) , now ( ) ) )
users . days7 = users . filter ( date_joined__range = ( date_today ( ) - timedelta ( days = 7 ) , now ( ) ) )
users . year = users . filter ( date_joined__year = date_today ( ) . year )
users . month = users . year . filter ( date_joined__month = date_today ( ) . month )
2012-03-13 20:54:30 +00:00
users . yesterday = users . filter ( date_joined__range = ( date_today ( ) - timedelta ( days = 1 ) , date_today ( ) ) )
2012-03-13 03:34:10 +00:00
users . gr = users . filter ( profile__goodreads_user_id__isnull = False )
users . lt = users . exclude ( profile__librarything_id = ' ' )
users . fb = users . filter ( profile__facebook_id__isnull = False )
users . tw = users . exclude ( profile__twitter_id = ' ' )
2012-03-08 03:06:30 +00:00
works = models . Work . objects
2012-03-07 19:42:16 +00:00
works . today = works . filter ( created__range = ( date_today ( ) , now ( ) ) )
works . days7 = works . filter ( created__range = ( date_today ( ) - timedelta ( days = 7 ) , now ( ) ) )
works . year = works . filter ( created__year = date_today ( ) . year )
works . month = works . year . filter ( created__month = date_today ( ) . month )
2012-03-13 20:54:30 +00:00
works . yesterday = works . filter ( created__range = ( date_today ( ) - timedelta ( days = 1 ) , date_today ( ) ) )
2012-03-08 03:06:30 +00:00
works . wishedby2 = works . filter ( num_wishes__gte = 2 )
works . wishedby20 = works . filter ( num_wishes__gte = 20 )
works . wishedby5 = works . filter ( num_wishes__gte = 5 )
works . wishedby50 = works . filter ( num_wishes__gte = 50 )
works . wishedby10 = works . filter ( num_wishes__gte = 10 )
works . wishedby100 = works . filter ( num_wishes__gte = 100 )
ebooks = models . Ebook . objects
2012-03-07 19:42:16 +00:00
ebooks . today = ebooks . filter ( created__range = ( date_today ( ) , now ( ) ) )
ebooks . days7 = ebooks . filter ( created__range = ( date_today ( ) - timedelta ( days = 7 ) , now ( ) ) )
ebooks . year = ebooks . filter ( created__year = date_today ( ) . year )
ebooks . month = ebooks . year . filter ( created__month = date_today ( ) . month )
2012-03-13 20:54:30 +00:00
ebooks . yesterday = ebooks . filter ( created__range = ( date_today ( ) - timedelta ( days = 1 ) , date_today ( ) ) )
2012-03-08 03:06:30 +00:00
wishlists = models . Wishlist . objects . exclude ( wishes__isnull = True )
2012-03-07 19:42:16 +00:00
wishlists . today = wishlists . filter ( created__range = ( date_today ( ) , now ( ) ) )
wishlists . days7 = wishlists . filter ( created__range = ( date_today ( ) - timedelta ( days = 7 ) , now ( ) ) )
wishlists . year = wishlists . filter ( created__year = date_today ( ) . year )
wishlists . month = wishlists . year . filter ( created__month = date_today ( ) . month )
2012-03-13 03:34:10 +00:00
if date_today ( ) . day == 1 :
wishlists . yesterday = wishlists . filter ( created__range = ( date_today ( ) - timedelta ( days = 1 ) , date_today ( ) ) )
else :
wishlists . yesterday = wishlists . month . filter ( created__day = date_today ( ) . day - 1 )
2012-03-08 03:06:30 +00:00
return {
' users ' : users ,
' works ' : works ,
' ebooks ' : ebooks ,
' wishlists ' : wishlists ,
}
2012-01-03 21:17:04 +00:00
class FAQView ( TemplateView ) :
2012-01-31 15:07:52 +00:00
template_name = " faq.html "
def get_context_data ( self , * * kwargs ) :
location = self . kwargs [ " location " ]
sublocation = self . kwargs [ " sublocation " ]
return { ' location ' : location , ' sublocation ' : sublocation }
2011-10-25 01:29:01 +00:00
class GoodreadsDisplayView ( TemplateView ) :
template_name = " goodreads_display.html "
def get_context_data ( self , * * kwargs ) :
context = super ( GoodreadsDisplayView , self ) . get_context_data ( * * kwargs )
session = self . request . session
gr_client = GoodreadsClient ( key = settings . GOODREADS_API_KEY , secret = settings . GOODREADS_API_SECRET )
2011-10-29 22:40:00 +00:00
user = self . request . user
2011-11-01 16:50:05 +00:00
if user . is_authenticated ( ) :
api_key = ApiKey . objects . filter ( user = user ) [ 0 ] . key
context [ ' api_key ' ] = api_key
2011-10-25 01:29:01 +00:00
2011-10-29 22:40:00 +00:00
if user . profile . goodreads_user_id is None :
2011-10-25 01:29:01 +00:00
# calculate the Goodreads authorization URL
( context [ " goodreads_auth_url " ] , request_token ) = gr_client . begin_authorization ( self . request . build_absolute_uri ( reverse ( ' goodreads_cb ' ) ) )
2011-10-29 22:40:00 +00:00
logger . info ( " goodreads_auth_url: %s " % ( context [ " goodreads_auth_url " ] ) )
2011-10-25 01:29:01 +00:00
# store request token in session so that we can redeem it for auth_token if authorization works
session [ ' goodreads_request_token ' ] = request_token [ ' oauth_token ' ]
session [ ' goodreads_request_secret ' ] = request_token [ ' oauth_token_secret ' ]
2011-10-29 22:40:00 +00:00
else :
2011-11-01 00:26:05 +00:00
gr_shelves = gr_client . shelves_list ( user_id = user . profile . goodreads_user_id )
context [ " shelves_info " ] = gr_shelves
gr_shelf_load_form = GoodreadsShelfLoadingForm ( )
# load the shelves into the form
2011-11-10 23:14:33 +00:00
choices = [ ( ' all: %d ' % ( gr_shelves [ " total_book_count " ] ) , ' all ( %d ) ' % ( gr_shelves [ " total_book_count " ] ) ) ] + \
[ ( " %s : %d " % ( s [ " name " ] , s [ " book_count " ] ) , " %s ( %d ) " % ( s [ " name " ] , s [ " book_count " ] ) ) for s in gr_shelves [ " user_shelves " ] ]
2011-11-15 20:51:38 +00:00
gr_shelf_load_form . fields [ ' goodreads_shelf_name_number ' ] . widget = Select ( choices = tuple ( choices ) )
2011-10-25 01:29:01 +00:00
2011-11-01 00:26:05 +00:00
context [ " gr_shelf_load_form " ] = gr_shelf_load_form
2011-11-10 23:14:33 +00:00
# also load any CeleryTasks associated with the user
context [ " celerytasks " ] = models . CeleryTask . objects . filter ( user = user )
2011-10-25 01:29:01 +00:00
return context
2011-10-29 22:40:00 +00:00
2011-11-16 22:16:57 +00:00
@login_required
def goodreads_auth ( request ) :
# calculate the Goodreads authorization URL
gr_client = GoodreadsClient ( key = settings . GOODREADS_API_KEY , secret = settings . GOODREADS_API_SECRET )
( goodreads_auth_url , request_token ) = gr_client . begin_authorization ( request . build_absolute_uri ( reverse ( ' goodreads_cb ' ) ) )
logger . info ( " goodreads_auth_url: %s " % ( goodreads_auth_url ) )
# store request token in session so that we can redeem it for auth_token if authorization works
request . session [ ' goodreads_request_token ' ] = request_token [ ' oauth_token ' ]
request . session [ ' goodreads_request_secret ' ] = request_token [ ' oauth_token_secret ' ]
return HttpResponseRedirect ( goodreads_auth_url )
2011-10-29 22:40:00 +00:00
@login_required
2011-10-25 01:29:01 +00:00
def goodreads_cb ( request ) :
2011-10-29 22:40:00 +00:00
""" handle callback from Goodreads """
2011-10-25 01:29:01 +00:00
session = request . session
authorized_flag = request . GET [ ' authorize ' ] # is it '1'?
request_oauth_token = request . GET [ ' oauth_token ' ]
if authorized_flag == ' 1 ' :
request_token = { ' oauth_token ' : session . get ( ' goodreads_request_token ' ) ,
' oauth_token_secret ' : session . get ( ' goodreads_request_secret ' ) }
gr_client = GoodreadsClient ( key = settings . GOODREADS_API_KEY , secret = settings . GOODREADS_API_SECRET )
access_token = gr_client . complete_authorization ( request_token )
2011-10-29 22:40:00 +00:00
# store the access token in the user profile
profile = request . user . profile
profile . goodreads_auth_token = access_token [ " oauth_token " ]
profile . goodreads_auth_secret = access_token [ " oauth_token_secret " ]
2011-10-25 01:29:01 +00:00
# let's get the userid, username
user = gr_client . auth_user ( )
2011-10-29 22:40:00 +00:00
profile . goodreads_user_id = user [ " userid " ]
profile . goodreads_user_name = user [ " name " ]
profile . goodreads_user_link = user [ " link " ]
profile . save ( ) # is this needed?
2011-10-25 01:29:01 +00:00
# redirect to the Goodreads display page -- should observe some next later
2011-11-16 20:45:33 +00:00
return HttpResponseRedirect ( reverse ( ' home ' ) )
2011-11-01 00:26:05 +00:00
@require_POST
@login_required
@csrf_exempt
def goodreads_flush_assoc ( request ) :
2011-10-29 22:40:00 +00:00
user = request . user
if user . is_authenticated ( ) :
profile = user . profile
profile . goodreads_user_id = None
profile . goodreads_user_name = None
profile . goodreads_user_link = None
profile . goodreads_auth_token = None
profile . goodreads_auth_secret = None
profile . save ( )
2011-11-10 15:36:17 +00:00
logger . info ( ' Goodreads association flushed for user %s ' , user )
2011-11-01 00:26:05 +00:00
return HttpResponseRedirect ( reverse ( ' goodreads_display ' ) )
2011-10-25 01:29:01 +00:00
2011-11-01 00:26:05 +00:00
@require_POST
@login_required
@csrf_exempt
def goodreads_load_shelf ( request ) :
"""
a view to allow user load goodreads shelf into her wishlist
"""
# Should be moved to the API
2011-11-15 20:51:38 +00:00
goodreads_shelf_name_number = request . POST . get ( ' goodreads_shelf_name_number ' , ' all:0 ' )
2011-11-01 00:26:05 +00:00
user = request . user
try :
2011-11-10 23:14:33 +00:00
# parse out shelf name and expected number of books
2011-11-15 20:51:38 +00:00
( shelf_name , expected_number_of_books ) = re . match ( r ' ^(.*):( \ d+)$ ' , goodreads_shelf_name_number ) . groups ( )
2011-11-10 23:14:33 +00:00
expected_number_of_books = int ( expected_number_of_books )
logger . info ( ' Adding task to load shelf %s to user %s with %d books ' , shelf_name , user , expected_number_of_books )
load_task_name = " load_goodreads_shelf_into_wishlist "
load_task = getattr ( tasks , load_task_name )
2012-02-16 18:19:36 +00:00
task_id = load_task . delay ( user . id , shelf_name , expected_number_of_books = expected_number_of_books )
2011-11-10 23:14:33 +00:00
ct = models . CeleryTask ( )
ct . task_id = task_id
ct . function_name = load_task_name
ct . user = user
ct . description = " Loading Goodread shelf %s to user %s with %s books " % ( shelf_name , user , expected_number_of_books )
ct . save ( )
2011-12-26 17:53:28 +00:00
return HttpResponse ( " <span style= ' margin: auto 10px auto 36px;vertical-align: middle;display: inline-block; ' >We ' re on it! <a href= ' JavaScript:window.location.reload() ' >Reload the page</a> to see the books we ' ve snagged so far.</span> " )
2011-11-01 00:26:05 +00:00
except Exception , e :
return HttpResponse ( " Error in loading shelf: %s " % ( e ) )
2011-11-10 15:36:17 +00:00
logger . info ( " Error in loading shelf for user %s : %s " , user , e )
2011-11-01 00:26:05 +00:00
2011-11-17 00:47:29 +00:00
2012-01-24 17:36:45 +00:00
@login_required
def goodreads_calc_shelves ( request ) :
# we should move towards calculating this only if needed (perhaps with Ajax), caching previous results, etc to speed up
# performance
if request . user . profile . goodreads_user_id is not None :
gr_client = GoodreadsClient ( key = settings . GOODREADS_API_KEY , secret = settings . GOODREADS_API_SECRET )
goodreads_shelves = gr_client . shelves_list ( user_id = request . user . profile . goodreads_user_id )
#goodreads_shelf_load_form = GoodreadsShelfLoadingForm()
## load the shelves into the form
#choices = [('all:%d' % (goodreads_shelves["total_book_count"]),'all (%d)' % (goodreads_shelves["total_book_count"]))] + \
# [("%s:%d" % (s["name"], s["book_count"]) ,"%s (%d)" % (s["name"],s["book_count"])) for s in goodreads_shelves["user_shelves"]]
#goodreads_shelf_load_form.fields['goodreads_shelf_name_number'].widget = Select(choices=tuple(choices))
else :
goodreads_shelf_load_form = None
return HttpResponse ( json . dumps ( goodreads_shelves ) , content_type = " application/json " )
2011-11-17 00:47:29 +00:00
@require_POST
@login_required
@csrf_exempt
def librarything_load ( request ) :
"""
a view to allow user load librarything library into her wishlist
"""
# Should be moved to the API
user = request . user
try :
# figure out expected_number_of_books later
lt_username = request . user . profile . librarything_id
2011-11-17 15:40:40 +00:00
logger . info ( ' Adding task to load librarything %s to user %s ' , lt_username , user )
2011-11-17 00:47:29 +00:00
load_task_name = " load_librarything_into_wishlist "
load_task = getattr ( tasks , load_task_name )
2012-02-16 18:19:36 +00:00
task_id = load_task . delay ( user . id , lt_username , None )
2011-11-17 00:47:29 +00:00
ct = models . CeleryTask ( )
ct . task_id = task_id
ct . function_name = load_task_name
ct . user = user
ct . description = " Loading LibraryThing collection of %s to user %s . " % ( lt_username , user )
ct . save ( )
2011-12-31 18:49:23 +00:00
2011-12-26 17:53:28 +00:00
return HttpResponse ( " <span style= ' margin: auto 10px auto 36px;vertical-align: middle;display: inline-block; ' >We ' re on it! <a href= ' JavaScript:window.location.reload() ' >Reload the page</a> to see the books we ' ve snagged so far.</span> " )
2011-11-17 00:47:29 +00:00
except Exception , e :
return HttpResponse ( " Error in loading LibraryThing library: %s " % ( e ) )
logger . info ( " Error in loading LibraryThing for user %s : %s " , user , e )
2011-11-01 00:26:05 +00:00
@require_POST
@login_required
2011-11-01 17:41:39 +00:00
@csrf_exempt
2011-11-01 00:26:05 +00:00
def clear_wishlist ( request ) :
2011-11-01 17:41:39 +00:00
try :
request . user . wishlist . works . clear ( )
2011-11-10 15:36:17 +00:00
logger . info ( " Wishlist for user %s cleared " , request . user )
2011-11-01 17:41:39 +00:00
return HttpResponse ( ' wishlist cleared ' )
except Exception , e :
return HttpResponse ( " Error in clearing wishlist: %s " % ( e ) )
2011-11-10 15:36:17 +00:00
logger . info ( " Error in clearing wishlist for user %s : %s " , request . user , e )
2011-11-01 21:24:18 +00:00
2011-11-16 18:20:10 +00:00
class LibraryThingView ( FormView ) :
template_name = " librarything.html "
form_class = LibraryThingForm
def get_context_data ( self , * * kwargs ) :
context = super ( LibraryThingView , self ) . get_context_data ( * * kwargs )
form = kwargs [ ' form ' ]
# get the books for the lt_username in the form
lt_username = self . request . GET . get ( " lt_username " , None )
if lt_username is not None :
lt = librarything . LibraryThing ( username = lt_username )
context . update ( { ' books ' : list ( lt . parse_user_catalog ( view_style = 5 ) ) } )
else :
context . update ( { ' books ' : None } )
2011-11-17 15:40:40 +00:00
# try picking up the LibraryThing api key -- and set to None if not available. Not being used for
# anything crucial at this moment, so a None is ok here
try :
context . update ( { ' lt_api_key ' : settings . LIBRARYTHING_API_KEY } )
except :
pass
2011-11-16 18:20:10 +00:00
return context
def form_valid ( self , form ) :
return super ( LibraryThingView , self ) . form_valid ( form )
2011-11-10 23:14:33 +00:00
@require_POST
@login_required
@csrf_exempt
def clear_celery_tasks ( request ) :
try :
request . user . tasks . clear ( )
logger . info ( " Celery tasks for user %s cleared " , request . user )
return HttpResponse ( ' Celery Tasks List cleared ' )
except Exception , e :
return HttpResponse ( " Error in clearing Celery Tasks: %s " % ( e ) )
logger . info ( " Error in clearing Celery Tasks for user %s : %s " , request . user , e )
2011-11-06 21:46:46 +00:00
2011-11-10 01:31:31 +00:00
def celery_test ( request ) :
return HttpResponse ( " celery_test " )
2011-12-05 05:56:24 +00:00
# routing views that try to redirect to the works page on a 3rd party site
#
# TODO: need to queue up a task to look up IDs if we have to fallback to
# routing based on ISBN or search
def work_librarything ( request , work_id ) :
work = get_object_or_404 ( models . Work , id = work_id )
2011-12-20 04:26:55 +00:00
isbn = work . first_isbn_13 ( )
2011-12-05 05:56:24 +00:00
if work . librarything_id :
url = work . librarything_url
elif isbn :
# TODO: do the redirect here and capture the work id?
2011-12-20 04:26:55 +00:00
url = " http://www.librarything.com/isbn/ %s " % isbn
2011-12-05 05:56:24 +00:00
else :
term = work . title + " " + work . author ( )
2012-03-01 13:53:55 +00:00
q = urlencode ( { ' searchtpe ' : ' work ' , ' term ' : term } )
2011-12-05 05:56:24 +00:00
url = " http://www.librarything.com/search.php? " + q
return HttpResponseRedirect ( url )
def work_openlibrary ( request , work_id ) :
work = get_object_or_404 ( models . Work , id = work_id )
2012-01-17 21:50:19 +00:00
isbns = [ " ISBN: " + i . value for i in work . identifiers . filter ( type = ' isbn ' ) ]
2011-12-06 14:53:53 +00:00
url = None
2011-12-05 05:56:24 +00:00
if work . openlibrary_id :
url = work . openlibrary_url
elif len ( isbns ) > 0 :
isbns = " , " . join ( isbns )
2011-12-06 14:53:53 +00:00
u = ' http://openlibrary.org/api/books?bibkeys= %s &jscmd=data&format=json ' % isbns
2012-03-10 16:03:58 +00:00
try :
j = json . loads ( requests . get ( u ) . content )
# as long as there were some matches get the first one and route to it
if len ( j . keys ( ) ) > 0 :
first = j . keys ( ) [ 0 ]
url = " http://openlibrary.org " + j [ first ] [ ' key ' ]
except ValueError :
# fail at openlibrary
logger . warning ( " failed to get OpenLibrary json at %s " % u )
2011-12-06 14:53:53 +00:00
# fall back to doing a search on openlibrary
if not url :
2012-03-01 13:53:55 +00:00
q = urlencode ( { ' q ' : work . title + " " + work . author ( ) } )
2011-12-05 05:56:24 +00:00
url = " http://openlibrary.org/search? " + q
return HttpResponseRedirect ( url )
def work_goodreads ( request , work_id ) :
work = get_object_or_404 ( models . Work , id = work_id )
2011-12-20 04:26:55 +00:00
isbn = work . first_isbn_13 ( )
2011-12-05 05:56:24 +00:00
if work . goodreads_id :
url = work . goodreads_url
elif isbn :
2011-12-20 04:26:55 +00:00
url = " http://www.goodreads.com/book/isbn/ %s " % isbn
2011-12-05 05:56:24 +00:00
else :
2012-03-01 13:53:55 +00:00
q = urlencode ( { ' query ' : work . title + " " + work . author ( ) } )
2011-12-05 05:56:24 +00:00
url = " http://www.goodreads.com/search? " + q
return HttpResponseRedirect ( url )
2011-12-29 01:43:52 +00:00
2012-01-02 14:39:11 +00:00
@login_required
2011-12-29 01:43:52 +00:00
def emailshare ( request ) :
2011-12-31 18:49:23 +00:00
if request . method == ' POST ' :
form = EmailShareForm ( request . POST )
if form . is_valid ( ) :
subject = form . cleaned_data [ ' subject ' ]
message = form . cleaned_data [ ' message ' ]
sender = form . cleaned_data [ ' sender ' ]
recipient = form . cleaned_data [ ' recipient ' ]
send_mail ( subject , message , sender , [ recipient ] )
try :
next = form . cleaned_data [ ' next ' ]
except :
next = ' '
return HttpResponseRedirect ( next )
else :
try :
next = request . GET [ ' next ' ]
2012-03-12 17:18:11 +00:00
work_id = next . split ( ' / ' ) [ - 2 ]
work_id = int ( work_id )
book = models . Work . objects . get ( pk = work_id )
title = book . title
# if title requires unicode let's ignore it for now
try :
2012-03-23 15:15:37 +00:00
title = ' , ' + str ( title ) + ' , '
2012-03-12 17:18:11 +00:00
except :
2012-03-23 15:15:37 +00:00
title = ' '
2012-03-12 17:18:11 +00:00
try :
2012-03-23 15:15:37 +00:00
status = book . last_campaign ( ) . status
2012-03-12 17:18:11 +00:00
except :
2012-03-23 15:15:37 +00:00
status = None
2012-03-12 17:18:11 +00:00
# customize the call to action depending on campaign status
if status == ' ACTIVE ' :
message = ' Help me unglue one of my favorite books ' + title + ' on Unglue.It: ' + next + ' . If enough of us pledge to unglue this book, the creator will be paid and the ebook will become free to everyone on earth. '
else :
2012-03-23 15:15:37 +00:00
message = ' Help me unglue one of my favorite books ' + title + ' on Unglue.It: ' + next + ' . If enough of us wishlist this book, Unglue.It may start a campaign to pay the creator and make the ebook free to everyone on earth. '
2012-03-12 17:18:11 +00:00
form = EmailShareForm ( initial = { ' next ' : next , ' subject ' : ' Come see one of my favorite books on Unglue.It ' , ' message ' : message } )
2011-12-31 18:49:23 +00:00
except :
next = ' '
sender = ' '
2012-03-12 17:18:11 +00:00
form = EmailShareForm ( initial = { ' next ' : next , ' subject ' : ' Come join me on Unglue.It ' , ' message ' : " I ' m ungluing books on Unglue.It. Together we ' re paying creators and making ebooks free to everyone on earth. Join me! http://unglue.it " } )
2011-12-29 01:43:52 +00:00
2011-12-31 18:49:23 +00:00
return render ( request , " emailshare.html " , { ' form ' : form } )
2012-01-09 20:53:09 +00:00
def feedback ( request ) :
num1 = randint ( 0 , 10 )
num2 = randint ( 0 , 10 )
sum = num1 + num2
2012-01-31 15:07:52 +00:00
2012-01-09 20:53:09 +00:00
if request . method == ' POST ' :
form = FeedbackForm ( request . POST )
if form . is_valid ( ) :
subject = form . cleaned_data [ ' subject ' ]
message = form . cleaned_data [ ' message ' ]
sender = form . cleaned_data [ ' sender ' ]
recipient = ' support@gluejar.com '
page = form . cleaned_data [ ' page ' ]
2012-01-25 19:55:03 +00:00
useragent = request . META [ ' HTTP_USER_AGENT ' ]
2012-01-16 00:02:50 +00:00
if request . user . is_anonymous ( ) :
2012-01-31 15:07:52 +00:00
ungluer = " (not logged in) "
2012-01-16 00:02:50 +00:00
else :
2012-01-31 15:07:52 +00:00
ungluer = request . user . username
2012-01-25 19:55:03 +00:00
message = " <<<This feedback is about " + page + " . Original user message follows \n from " + sender + " , ungluer name " + ungluer + " \n with user agent " + useragent + " \n >>> \n " + message
2012-01-09 20:53:09 +00:00
send_mail ( subject , message , sender , [ recipient ] )
return render ( request , " thanks.html " , { " page " : page } )
else :
2012-01-31 15:07:52 +00:00
num1 = request . POST [ ' num1 ' ]
num2 = request . POST [ ' num2 ' ]
2012-01-09 20:53:09 +00:00
else :
2012-01-31 15:07:52 +00:00
if request . user . is_authenticated ( ) :
sender = request . user . email ;
else :
sender = ' '
try :
page = request . GET [ ' page ' ]
except :
page = ' / '
2012-01-09 20:53:09 +00:00
form = FeedbackForm ( initial = { " sender " : sender , " subject " : " Feedback on page " + page , " page " : page , " num1 " : num1 , " num2 " : num2 , " answer " : sum } )
return render ( request , " feedback.html " , { ' form ' : form , ' num1 ' : num1 , ' num2 ' : num2 } )
2012-01-09 21:13:49 +00:00
2012-02-03 15:22:53 +00:00
def comment ( request ) :
2012-02-23 20:40:45 +00:00
latest_comments = Comment . objects . all ( ) . order_by ( ' -submit_date ' ) [ : 20 ]
2012-02-05 00:06:53 +00:00
return render ( request , " comments.html " , { ' latest_comments ' : latest_comments } )