2013-03-26 17:54:03 +00:00
'''
2013-06-03 16:31:39 +00:00
external library imports
2013-03-26 17:54:03 +00:00
'''
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
2013-03-26 17:54:03 +00:00
import requests
2013-08-14 21:29:38 +00:00
import random
2013-03-26 17:54:03 +00:00
import oauth2 as oauth
2012-03-13 20:57:42 +00:00
2012-09-18 18:16:06 +00:00
from datetime import timedelta , date
2013-03-26 17:54:03 +00:00
from decimal import Decimal as D
from itertools import islice , chain
from notification import models as notification
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-23 01:34:24 +00:00
from xml . etree import ElementTree as ET
2013-07-19 16:47:36 +00:00
from xml . sax import SAXParseException
2013-03-26 17:54:03 +00:00
from tastypie . models import ApiKey
'''
django imports
'''
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
2012-01-02 14:39:11 +00:00
from django . contrib import messages
2013-07-15 20:35:41 +00:00
from django . contrib . admin . views . decorators import staff_member_required
2012-02-23 20:40:45 +00:00
from django . contrib . auth . decorators import login_required
2013-06-03 16:31:39 +00:00
from django . contrib . auth . models import User
2013-08-14 21:29:38 +00:00
from django . contrib . auth . views import login , password_reset
2012-02-03 15:22:53 +00:00
from django . contrib . comments import Comment
2012-05-12 15:12:27 +00:00
from django . contrib . sites . models import Site
2013-03-26 17:54:03 +00:00
from django . core import signing
2013-06-10 15:57:59 +00:00
from django . core . exceptions import ObjectDoesNotExist , ValidationError
2013-07-24 18:52:01 +00:00
from django . core . files . storage import default_storage
2013-05-31 21:15:22 +00:00
from django . core . files . temp import NamedTemporaryFile
from django . core . mail import EmailMessage
2013-07-15 20:35:41 +00:00
from django . core . urlresolvers import reverse , reverse_lazy
2013-06-10 15:57:59 +00:00
from django . core . validators import validate_email
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
2013-06-03 16:31:39 +00:00
from django . forms . models import modelformset_factory , inlineformset_factory
from django . http import (
HttpResponseRedirect ,
Http404 ,
HttpResponse ,
HttpResponseNotFound
)
2013-03-26 17:54:03 +00:00
from django . shortcuts import render , render_to_response , get_object_or_404
2013-05-03 18:48:36 +00:00
from django . template import TemplateDoesNotExist
2012-04-25 02:20:10 +00:00
from django . template . loader import render_to_string
2013-03-26 17:54:03 +00:00
from django . utils . http import urlencode
from django . utils . translation import ugettext_lazy as _
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
2013-03-26 17:54:03 +00:00
'''
regluit imports
'''
2013-06-03 16:31:39 +00:00
from regluit . core import (
tasks ,
models ,
bookloader ,
librarything ,
userlists ,
2013-07-17 14:34:01 +00:00
goodreads ,
ungluify_record
2013-06-03 16:31:39 +00:00
)
2013-04-16 20:46:25 +00:00
from regluit . core . bookloader import merge_works , detach_edition
2013-03-26 17:54:03 +00:00
from regluit . core . goodreads import GoodreadsClient
from regluit . core . search import gluejar_search
2013-03-01 14:46:52 +00:00
from regluit . core . signals import supporter_message
2013-04-08 20:51:08 +00:00
from regluit . core . tasks import send_mail_task , emit_notifications
2013-03-26 17:54:03 +00:00
2013-05-31 19:19:58 +00:00
from regluit . frontend . forms import (
UserData ,
ProfileForm ,
CampaignPledgeForm ,
2013-08-16 19:49:44 +00:00
CampaignPurchaseForm ,
2013-05-31 19:19:58 +00:00
GoodreadsShelfLoadingForm ,
RightsHolderForm ,
UserClaimForm ,
LibraryThingForm ,
OpenCampaignForm ,
getManageCampaignForm ,
DonateForm ,
CampaignAdminForm ,
EmailShareForm ,
FeedbackForm ,
EbookForm ,
2013-06-17 22:53:21 +00:00
EbookFileForm ,
2013-05-31 19:19:58 +00:00
CustomPremiumForm ,
2013-06-17 22:53:21 +00:00
OfferForm ,
2013-05-31 19:19:58 +00:00
EditManagersForm ,
EditionForm ,
PledgeCancelForm ,
getTransferCreditForm ,
CCForm ,
CloneCampaignForm ,
PlainCCForm ,
WorkForm ,
OtherWorkForm ,
MsgForm ,
AuthForm ,
PressForm ,
2013-07-15 20:35:41 +00:00
KindleEmailForm ,
2013-07-23 16:23:04 +00:00
MARCUngluifyForm ,
MARCFormatForm
2013-05-31 19:19:58 +00:00
)
2013-03-26 17:54:03 +00:00
from regluit . payment import baseprocessor , stripelib
from regluit . payment . credit import credit_transaction
2011-10-13 21:13:37 +00:00
from regluit . payment . manager import PaymentManager
2013-03-26 17:54:03 +00:00
from regluit . payment . models import Transaction , Account , Sent , CreditLog
2013-05-31 19:19:58 +00:00
from regluit . payment . parameters import (
TRANSACTION_STATUS_ACTIVE ,
TRANSACTION_STATUS_COMPLETE ,
TRANSACTION_STATUS_CANCELED ,
TRANSACTION_STATUS_ERROR ,
TRANSACTION_STATUS_FAILED ,
TRANSACTION_STATUS_INCOMPLETE ,
TRANSACTION_STATUS_NONE ,
TRANSACTION_STATUS_MODIFIED ,
PAYMENT_TYPE_AUTHORIZATION ,
PAYMENT_TYPE_INSTANT ,
PAYMENT_HOST_STRIPE ,
PAYMENT_HOST_NONE
)
2011-12-19 06:33:13 +00:00
2013-03-26 17:54:03 +00:00
from regluit . utils . localdatetime import now , date_today
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-07-07 22:13:05 +00:00
def static_redirect_view ( request , file_name , dir = " " ) :
return HttpResponseRedirect ( ' /static/ ' + dir + " / " + file_name )
2012-03-08 14:36:59 +00:00
def slideshow ( max ) :
ending = models . Campaign . objects . filter ( status = ' ACTIVE ' ) . order_by ( ' deadline ' )
count = ending . count ( )
j = 0
2012-06-13 12:41:23 +00:00
worklist = [ ]
if max > count :
# add all the works with active campaigns
for campaign in ending :
worklist . append ( campaign . work )
2012-09-11 03:47:06 +00:00
2012-06-13 12:41:23 +00:00
# then fill out the rest of the list with popular but inactive works
remainder = max - count
2012-10-15 04:59:46 +00:00
remainder_works = models . Work . objects . filter ( wishlists__user = recommended_user ) . exclude ( campaigns__status = ' ACTIVE ' ) . exclude ( campaigns__status = ' SUCCESSFUL ' ) [ : remainder ]
2012-06-13 12:41:23 +00:00
worklist . extend ( remainder_works )
2012-03-08 14:36:59 +00:00
else :
2012-06-13 12:41:23 +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-23 15:15:37 +00:00
2012-03-08 14:36:59 +00:00
return worklist
2011-10-13 16:23:57 +00:00
2013-06-10 13:29:18 +00:00
def process_kindle_email ( request ) :
"""
check for kindle_email in session in case this is a redirect after
download + login / account creation ; add kindle email to profile
"""
user = request . user
if user . is_authenticated ( ) and request . session . has_key ( ' kindle_email ' ) :
user . profile . kindle_email = request . session [ ' kindle_email ' ]
user . profile . save ( )
2013-06-26 13:46:56 +00:00
request . session . pop ( ' kindle_email ' )
2013-06-10 13:29:18 +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 ' ) :
2012-05-15 18:18:17 +00:00
response = HttpResponseRedirect ( urllib . unquote ( urllib . unquote ( request . COOKIES [ ' next ' ] ) ) )
2012-03-23 15:15:37 +00:00
response . delete_cookie ( ' next ' )
return response
else :
return HttpResponseRedirect ( ' / ' )
2012-08-24 19:14:32 +00:00
def safe_get_work ( work_id ) :
2012-08-29 19:56:14 +00:00
"""
use this rather than querying the db directly for a work by id
"""
2012-08-24 19:14:32 +00:00
try :
work = models . Work . objects . get ( id = work_id )
except models . Work . DoesNotExist :
try :
work = models . WasWork . objects . get ( was = work_id ) . work
except models . WasWork . DoesNotExist :
raise Http404
return work
2013-02-07 20:25:14 +00:00
def cover_width ( work ) :
if work . percent_of_goal ( ) < 100 :
cover_width = 100 - work . percent_of_goal ( )
else :
cover_width = 0
return cover_width
2012-03-13 20:57:42 +00:00
2012-05-24 19:29:45 +00:00
def home ( request , landing = False ) :
if request . user . is_authenticated ( ) and landing == False :
2011-09-27 09:27:15 +00:00
return HttpResponseRedirect ( reverse ( ' supporter ' ,
args = [ request . user . username ] ) )
2013-03-26 18:55:50 +00:00
"""
use campaigns instead of works so that we can order by amount left ,
drive interest toward most - nearly - successful
"""
top_campaigns = models . Campaign . objects . filter ( status = " ACTIVE " ) . order_by ( ' left ' ) [ : 4 ]
2013-06-05 19:05:14 +00:00
coming_soon = [ ]
if not top_campaigns :
coming_soon = models . Campaign . objects . filter ( status = " INITIALIZED " ) . order_by ( ' -work__num_wishes ' ) [ : 4 ]
2013-03-26 18:55:50 +00:00
2013-03-28 15:12:55 +00:00
most_wished = models . Work . objects . order_by ( ' -num_wishes ' ) [ : 4 ]
2013-06-05 19:06:07 +00:00
unglued_books = models . Work . objects . filter ( campaigns__status = " SUCCESSFUL " ) . order_by ( ' -campaigns__deadline ' ) [ : 4 ]
2012-01-15 23:03:54 +00:00
2013-03-26 17:54:03 +00:00
"""
get various recent types of site activity
"""
latest_comments = Comment . objects . order_by (
' -submit_date '
) [ : 10 ]
latest_pledges = Transaction . objects . filter (
anonymous = False
2013-03-28 15:38:40 +00:00
) . only (
' date_created ' , ' user ' , ' campaign '
2013-03-26 17:54:03 +00:00
) . order_by (
' -date_created '
) [ : 10 ]
latest_wishes = models . Wishes . objects . order_by (
' -created '
) [ : 10 ]
2012-03-08 14:36:59 +00:00
2013-03-26 17:54:03 +00:00
"""
2013-03-26 18:55:50 +00:00
for each event , we ' ll be passing its object and type to the template
2013-03-26 17:54:03 +00:00
( and preserving its date for sorting purposes )
"""
latest_comments_tuple = map (
2013-03-28 15:38:40 +00:00
lambda x : ( x . submit_date , x , ' comment ' ) ,
2013-03-26 17:54:03 +00:00
latest_comments
)
latest_pledges_tuple = map (
2013-03-28 15:38:40 +00:00
lambda x : ( x . date_created , x , ' pledge ' ) ,
2013-03-26 17:54:03 +00:00
latest_pledges
)
latest_wishes_tuple = map (
2013-03-28 15:38:40 +00:00
lambda x : ( x . created , x , ' wish ' ) ,
2013-03-26 17:54:03 +00:00
latest_wishes
)
2013-03-26 18:55:50 +00:00
"""
merge latest actions into a single list , sorted by date , to loop through in template
"""
2013-03-26 17:54:03 +00:00
latest_actions = sorted (
chain ( latest_comments_tuple , latest_pledges_tuple , latest_wishes_tuple ) ,
key = lambda instance : instance [ 0 ] ,
reverse = True
)
2013-03-22 19:47:03 +00:00
if request . user . is_authenticated ( ) :
2013-03-26 17:54:03 +00:00
events = latest_actions [ : 12 ]
2013-03-22 19:47:03 +00:00
else :
2013-03-26 17:54:03 +00:00
events = latest_actions [ : 6 ]
2013-03-22 19:47:03 +00:00
2013-06-05 19:05:14 +00:00
return render (
request ,
' home.html ' ,
{
' suppress_search_box ' : True ,
' events ' : events ,
' top_campaigns ' : top_campaigns ,
' coming_soon ' : coming_soon ,
' unglued_books ' : unglued_books ,
' most_wished ' : most_wished
}
)
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
2012-07-07 22:13:05 +00:00
def acks ( request , work ) :
return render ( request , ' front_matter.html ' , { ' campaign ' : work . last_campaign ( ) } )
2013-03-08 02:48:56 +00:00
def superlogin ( request , * * kwargs ) :
extra_context = None
if request . method == ' POST ' and request . user . is_anonymous ( ) :
username = request . POST . get ( " username " , " " )
try :
user = models . User . objects . get ( username = username )
extra_context = { " socials " : user . profile . social_auths }
except :
pass
2013-03-29 15:50:07 +00:00
if request . GET . has_key ( " add " ) :
request . session [ " add_wishlist " ] = request . GET [ " add " ]
2013-03-21 14:14:23 +00:00
return login ( request , extra_context = extra_context , authentication_form = AuthForm , * * kwargs )
2013-08-14 21:29:38 +00:00
@login_required
def social_auth_reset_password ( request ) :
if not request . user . has_usable_password ( ) :
request . user . set_password ( ' %010x ' % random . randrange ( 16 * * 10 ) )
request . user . save ( )
return password_reset ( request )
2013-03-08 02:48:56 +00:00
2011-11-06 23:54:48 +00:00
def work ( request , work_id , action = ' display ' ) :
2012-08-24 19:14:32 +00:00
work = safe_get_work ( work_id )
2012-07-07 22:13:05 +00:00
if action == " acks " :
return acks ( request , work )
2012-08-24 19:14:32 +00:00
2013-03-29 15:50:07 +00:00
# process waiting add request
if not request . user . is_anonymous ( ) and request . session . has_key ( " add_wishlist " ) :
add_url = request . session [ " add_wishlist " ]
if add_url == request . path :
request . user . wishlist . add_work ( work , " login " , notify = True )
request . session . pop ( " add_wishlist " )
2013-06-10 13:29:18 +00:00
process_kindle_email ( request )
2012-02-28 22:28:33 +00:00
if request . method == ' POST ' and not request . user . is_anonymous ( ) :
activetab = ' 4 '
else :
try :
activetab = request . GET [ ' tab ' ]
if activetab not in [ ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' ] :
activetab = ' 1 ' ;
except :
activetab = ' 1 ' ;
2012-08-24 19:14:32 +00:00
2013-02-25 23:31:37 +00:00
alert = ' '
2011-11-06 22:44:50 +00:00
campaign = work . last_campaign ( )
2012-09-11 03:51:22 +00:00
if campaign and campaign . edition and not request . user . is_staff :
2012-05-01 14:56:19 +00:00
editions = [ campaign . edition ]
else :
editions = work . editions . all ( ) . order_by ( ' -publication_date ' )
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-05-01 17:49:23 +00:00
2012-09-13 21:12:49 +00:00
logger . info ( " pledged: {0} " . format ( pledged ) )
2013-02-07 20:25:14 +00:00
cover_width_number = 0
2012-08-24 19:14:32 +00:00
try :
2012-09-11 03:47:06 +00:00
assert not ( work . last_campaign_status ( ) == ' ACTIVE ' and work . first_ebook ( ) )
2012-08-24 19:14:32 +00:00
except :
2012-09-11 03:47:06 +00:00
logger . warning ( " Campaign running for %s when ebooks are already available: why? " % work . title )
2012-05-13 19:33:54 +00:00
if work . last_campaign_status ( ) == ' ACTIVE ' :
2013-02-07 20:25:14 +00:00
cover_width_number = cover_width ( work )
2012-09-11 03:47:06 +00:00
2012-05-14 02:13:45 +00:00
if action == ' preview ' :
work . last_campaign_status = ' ACTIVE '
2012-05-11 18:13:09 +00:00
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 :
2012-04-27 21:14:57 +00:00
edition . hide_details = 1
if request . method == ' POST ' and not request . user . is_anonymous ( ) :
if request . POST . has_key ( ' ebook_ %d -edition ' % edition . id ) :
edition . ebook_form = EbookForm ( data = request . POST , prefix = ' ebook_ %d ' % edition . id )
if edition . ebook_form . is_valid ( ) :
edition . ebook_form . save ( )
alert = ' Thanks for adding an ebook to unglue.it! '
else :
edition . hide_details = 0
alert = ' your submitted ebook had errors '
else :
#edition.ebook_form = EbookForm( data = {'user':request.user.id, 'edition':edition.pk })
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
2012-08-24 19:14:32 +00:00
2011-11-06 22:44:50 +00:00
if campaign :
2012-07-23 11:41:20 +00:00
# pull up premiums explicitly tied to the campaign
# mandatory premiums are only displayed in pledge process
premiums = campaign . custom_premiums ( )
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-04-03 13:56:41 +00:00
active_claims = work . claim . all ( ) . filter ( status = ' active ' )
if active_claims . count ( ) == 1 :
2012-04-03 19:50:02 +00:00
claimstatus = ' one_active '
rights_holder_name = active_claims [ 0 ] . rights_holder . rights_holder_name
2012-04-03 13:56:41 +00:00
else :
rights_holder_name = None
2012-04-03 19:50:02 +00:00
pending_claims = work . claim . all ( ) . filter ( status = ' pending ' )
pending_claims_count = pending_claims . count ( )
if pending_claims_count > 1 :
claimstatus = ' disputed '
elif pending_claims_count == 1 :
claimstatus = ' one_pending '
rights_holder_name = pending_claims [ 0 ] . rights_holder . rights_holder_name
else :
claimstatus = ' open '
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 ,
2012-04-03 13:56:41 +00:00
' pledged ' : pledged ,
2012-03-23 15:09:51 +00:00
' activetab ' : activetab ,
2012-04-03 13:56:41 +00:00
' alert ' : alert ,
' claimstatus ' : claimstatus ,
' rights_holder_name ' : rights_holder_name ,
2013-02-07 20:25:14 +00:00
' cover_width ' : cover_width_number
2012-09-25 01:51:57 +00:00
} )
2011-11-21 03:23:51 +00:00
2013-06-17 22:53:21 +00:00
def edition_uploads ( request , edition_id ) :
if not request . user . is_authenticated ( ) :
return render ( request , " admins_only.html " )
try :
edition = models . Edition . objects . get ( id = edition_id )
except models . Edition . DoesNotExist :
raise Http404
if not request . user . is_staff :
if not request . user in edition . work . last_campaign ( ) . managers . all ( ) :
return render ( request , " admins_only.html " )
if request . method == ' POST ' :
form = EbookFileForm ( request . POST , request . FILES )
if form . is_valid ( ) :
form . save ( )
else :
form = EbookFileForm ( initial = { ' edition ' : edition } )
return render ( request , ' edition_uploads.html ' , {
' form ' : form , ' edition ' : edition ,
' ebook_files ' : models . EbookFile . objects . filter ( edition = edition )
} )
2012-05-14 05:07:02 +00:00
def new_edition ( request , work_id , edition_id , by = None ) :
2012-05-11 18:13:09 +00:00
if not request . user . is_authenticated ( ) :
return render ( request , " admins_only.html " )
# if the work and edition are set, we save the edition and set the work
language = ' en '
description = ' '
title = ' '
if work_id :
try :
work = models . Work . objects . get ( id = work_id )
except models . Work . DoesNotExist :
try :
work = models . WasWork . objects . get ( was = work_id ) . work
except models . WasWork . DoesNotExist :
raise Http404
language = work . language
description = work . description
title = work . title
else :
work = None
2012-05-14 05:07:02 +00:00
if not request . user . is_staff :
if by == ' rh ' and work is not None :
if not request . user in work . last_campaign ( ) . managers . all ( ) :
return render ( request , " admins_only.html " )
else :
return render ( request , " admins_only.html " )
2012-05-11 18:13:09 +00:00
if edition_id :
try :
edition = models . Edition . objects . get ( id = edition_id )
2013-06-17 22:53:21 +00:00
except models . Edition . DoesNotExist :
2012-05-11 18:13:09 +00:00
raise Http404
if work :
edition . work = work
language = edition . work . language
description = edition . work . description
else :
edition = models . Edition ( )
if work :
edition . work = work
if request . method == ' POST ' :
edition . new_author_names = request . POST . getlist ( ' new_author ' )
edition . new_subjects = request . POST . getlist ( ' new_subject ' )
if request . POST . has_key ( ' add_author_submit ' ) :
new_author_name = request . POST [ ' add_author ' ] . strip ( )
try :
author = models . Author . objects . get ( name = new_author_name )
except models . Author . DoesNotExist :
author = models . Author . objects . create ( name = new_author_name )
edition . new_author_names . append ( new_author_name )
form = EditionForm ( instance = edition , data = request . POST )
elif request . POST . has_key ( ' add_subject_submit ' ) :
new_subject = request . POST [ ' add_subject ' ] . strip ( )
try :
author = models . Subject . objects . get ( name = new_subject )
except models . Subject . DoesNotExist :
author = models . Subject . objects . create ( name = new_subject )
edition . new_subjects . append ( new_subject )
form = EditionForm ( instance = edition , data = request . POST )
else :
form = EditionForm ( instance = edition , data = request . POST )
if form . is_valid ( ) :
form . save ( )
if not work :
work = models . Work ( title = form . cleaned_data [ ' title ' ] , language = form . cleaned_data [ ' language ' ] , description = form . cleaned_data [ ' description ' ] )
work . save ( )
edition . work = work
edition . save ( )
else :
work . description = form . cleaned_data [ ' description ' ]
work . title = form . cleaned_data [ ' title ' ]
work . save ( )
2012-09-25 01:51:57 +00:00
2013-04-13 14:59:11 +00:00
id_msg = " "
for id_type in ( ' isbn ' , ' oclc ' , ' goog ' , ' thng ' , ' gdrd ' ) :
id_val = form . cleaned_data [ id_type ]
if id_val == ' delete ' :
edition . identifiers . filter ( type = id_type ) . delete ( )
elif id_val :
existing = models . Identifier . objects . filter ( type = id_type , value = form . cleaned_data [ id_type ] )
if existing . count ( ) and existing [ 0 ] . edition != edition :
return render ( request , ' new_edition.html ' , {
' form ' : form , ' edition ' : edition ,
' id_msg ' : " %s = %s already exists " % ( id_type , id_val ) ,
} )
else :
models . Identifier . set ( type = id_type , value = id_val , edition = edition , work = work )
2012-05-11 18:13:09 +00:00
for author_name in edition . new_author_names :
try :
author = models . Author . objects . get ( name = author_name )
except models . Author . DoesNotExist :
author = models . Author . objects . create ( name = author_name )
author . editions . add ( edition )
for subject_name in edition . new_subjects :
try :
subject = models . Subject . objects . get ( name = subject_name )
except models . Subject . DoesNotExist :
subject = models . Subject . objects . create ( name = subject_name )
subject . works . add ( work )
work_url = reverse ( ' work ' , kwargs = { ' work_id ' : edition . work . id } )
return HttpResponseRedirect ( work_url )
else :
form = EditionForm ( instance = edition , initial = {
' language ' : language ,
2013-04-13 14:59:11 +00:00
' publisher_name ' : edition . publisher_name ,
' isbn ' : edition . isbn_13 ,
' oclc ' : edition . oclc ,
2012-05-11 18:13:09 +00:00
' description ' : description ,
2013-04-13 14:59:11 +00:00
' title ' : title ,
' goog ' : edition . googlebooks_id ,
' gdrd ' : edition . goodreads_id ,
' thng ' : edition . librarything_id ,
2012-05-11 18:13:09 +00:00
} )
return render ( request , ' new_edition.html ' , {
2013-04-13 14:59:11 +00:00
' form ' : form , ' edition ' : edition ,
2012-05-11 18:13:09 +00:00
} )
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 = [ ]
2012-07-10 19:58:19 +00:00
if ( not request . user . is_authenticated ) or ( not request . user in campaign . managers . all ( ) and not request . user . is_staff ) :
2011-11-22 05:28:06 +00:00
campaign . not_manager = True
return render ( request , ' manage_campaign.html ' , { ' campaign ' : campaign } )
2012-05-04 13:56:41 +00:00
alerts = [ ]
activetab = ' #1 '
2013-06-17 22:53:21 +00:00
offers = campaign . work . offers . all ( )
for offer in offers :
offer . offer_form = OfferForm ( instance = offer , prefix = ' offer_ %d ' % offer . id )
2012-05-04 13:56:41 +00:00
2012-03-26 19:31:41 +00:00
if request . method == ' POST ' :
if request . POST . has_key ( ' add_premium ' ) :
postcopy = request . POST . copy ( )
postcopy [ ' type ' ] = ' CU '
new_premium_form = CustomPremiumForm ( data = postcopy )
if new_premium_form . is_valid ( ) :
new_premium_form . save ( )
alerts . append ( _ ( ' New premium has been added ' ) )
new_premium_form = CustomPremiumForm ( data = { ' campaign ' : campaign } )
else :
alerts . append ( _ ( ' New premium has not been added ' ) )
2012-05-01 14:56:19 +00:00
form = getManageCampaignForm ( instance = campaign )
2012-05-04 13:56:41 +00:00
activetab = ' #2 '
elif request . POST . has_key ( ' save ' ) or request . POST . has_key ( ' launch ' ) :
2012-05-01 14:56:19 +00:00
form = getManageCampaignForm ( instance = campaign , data = request . POST )
2012-03-26 19:31:41 +00:00
if form . is_valid ( ) :
form . save ( )
2013-08-09 23:00:54 +00:00
campaign . set_dollar_per_day ( )
2013-06-17 22:53:21 +00:00
if campaign . type == models . BUY2UNGLUE :
offers = campaign . work . create_offers ( )
for offer in offers :
offer . offer_form = OfferForm ( instance = offer , prefix = ' offer_ %d ' % offer . id )
2012-06-22 03:10:50 +00:00
campaign . update_left ( )
2012-03-26 19:31:41 +00:00
alerts . append ( _ ( ' Campaign data has been saved ' ) )
2012-05-04 13:56:41 +00:00
activetab = ' #2 '
2011-11-26 02:23:37 +00:00
else :
2012-03-26 19:31:41 +00:00
alerts . append ( _ ( ' Campaign data has NOT been saved ' ) )
if ' launch ' in request . POST . keys ( ) :
2012-05-04 13:56:41 +00:00
activetab = ' #3 '
2012-09-27 15:14:09 +00:00
if ( campaign . launchable and form . is_valid ( ) ) and ( not settings . IS_PREVIEW or request . user . is_staff ) :
2012-03-26 19:31:41 +00:00
campaign . activate ( )
alerts . append ( _ ( ' Campaign has been launched ' ) )
else :
alerts . append ( _ ( ' Campaign has NOT been launched ' ) )
new_premium_form = CustomPremiumForm ( data = { ' campaign ' : campaign } )
elif request . POST . has_key ( ' inactivate ' ) :
2012-05-04 13:56:41 +00:00
activetab = ' #2 '
2012-03-26 19:31:41 +00:00
if request . POST . has_key ( ' premium_id ' ) :
2012-05-08 14:51:04 +00:00
premiums_to_stop = request . POST . getlist ( ' premium_id ' )
2012-03-26 19:31:41 +00:00
for premium_to_stop in premiums_to_stop :
selected_premium = models . Premium . objects . get ( id = premium_to_stop )
if selected_premium . type == ' CU ' :
selected_premium . type = ' XX '
selected_premium . save ( )
alerts . append ( _ ( ' Premium %s has been inactivated ' % premium_to_stop ) )
2012-05-01 14:56:19 +00:00
form = getManageCampaignForm ( instance = campaign )
2012-03-26 19:31:41 +00:00
new_premium_form = CustomPremiumForm ( data = { ' campaign ' : campaign } )
2013-06-17 22:53:21 +00:00
elif request . POST . has_key ( ' change_offer ' ) :
for offer in offers :
if request . POST . has_key ( ' offer_ %d -work ' % offer . id ) :
offer . offer_form = OfferForm ( instance = offer , data = request . POST , prefix = ' offer_ %d ' % offer . id )
if offer . offer_form . is_valid ( ) :
offer . offer_form . save ( )
alerts . append ( _ ( ' Offer has been changed ' ) )
else :
alerts . append ( _ ( ' Offer has not been changed ' ) )
form = getManageCampaignForm ( instance = campaign )
new_premium_form = CustomPremiumForm ( data = { ' campaign ' : campaign } )
activetab = ' #2 '
2011-11-22 05:28:06 +00:00
else :
2012-05-01 14:56:19 +00:00
form = getManageCampaignForm ( instance = campaign )
2012-03-26 19:31:41 +00:00
new_premium_form = CustomPremiumForm ( data = { ' campaign ' : campaign } )
return render ( request , ' manage_campaign.html ' , {
' campaign ' : campaign ,
' form ' : form ,
' problems ' : campaign . problems ,
' alerts ' : alerts ,
2012-10-02 18:42:39 +00:00
' premiums ' : campaign . custom_premiums ( ) ,
2012-03-26 19:31:41 +00:00
' premium_form ' : new_premium_form ,
2013-06-17 22:53:21 +00:00
' work ' : campaign . work ,
2012-05-04 13:56:41 +00:00
' activetab ' : activetab ,
2013-06-17 22:53:21 +00:00
' offers ' : offers
2012-03-26 19:31:41 +00:00
} )
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 } )
2013-03-29 15:50:07 +00:00
# process waiting add request
if not request . user . is_anonymous ( ) and request . session . has_key ( " add_wishlist " ) :
add_url = request . session [ " add_wishlist " ]
if add_url == request . path :
request . user . wishlist . add_work ( edition . work , " login " , notify = True )
request . session . pop ( " add_wishlist " )
2011-11-22 01:12:13 +00:00
return HttpResponseRedirect ( work_url )
2011-10-20 03:31:16 +00:00
2013-04-24 15:14:25 +00:00
def download_ebook ( request , ebook_id ) :
2013-04-20 04:02:36 +00:00
ebook = get_object_or_404 ( models . Ebook , id = ebook_id )
ebook . increment ( )
2013-04-20 14:34:44 +00:00
logger . info ( " ebook: {0} , user_ip: {1} " . format ( ebook_id , request . META [ ' REMOTE_ADDR ' ] ) )
2013-04-20 04:02:36 +00:00
return HttpResponseRedirect ( ebook . url )
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
2012-07-21 20:26:16 +00:00
class FilterableListView ( ListView ) :
def get_queryset ( self ) :
if self . request . GET . has_key ( ' pub_lang ' ) :
if self . model is models . Campaign :
return self . get_queryset_all ( ) . filter ( work__language = self . request . GET [ ' pub_lang ' ] )
else :
return self . get_queryset_all ( ) . filter ( language = self . request . GET [ ' pub_lang ' ] )
else :
return self . get_queryset_all ( )
def get_context_data ( self , * * kwargs ) :
context = super ( FilterableListView , self ) . get_context_data ( * * kwargs )
if self . request . GET . has_key ( ' pub_lang ' ) :
context [ ' pub_lang ' ] = self . request . GET [ ' pub_lang ' ]
else :
context [ ' pub_lang ' ] = ' '
context [ ' show_langs ' ] = True
context [ ' WISHED_LANGS ' ] = settings . WISHED_LANGS
return context
2011-12-03 00:29:23 +00:00
recommended_user = User . objects . filter ( username = settings . UNGLUEIT_RECOMMENDED_USERNAME )
2012-07-21 20:26:16 +00:00
class WorkListView ( FilterableListView ) :
2011-12-03 00:29:23 +00:00
template_name = " work_list.html "
context_object_name = " work_list "
2013-03-07 02:54:12 +00:00
max_works = 100000
2011-12-03 00:29:23 +00:00
2012-07-21 20:26:16 +00:00
def get_queryset_all ( self ) :
2011-12-03 00:29:23 +00:00
facet = self . kwargs [ ' facet ' ]
if ( facet == ' popular ' ) :
2013-03-07 02:54:12 +00:00
return models . Work . objects . exclude ( num_wishes = 0 ) . order_by ( ' -num_wishes ' , ' id ' )
2011-12-03 00:29:23 +00:00
elif ( facet == ' recommended ' ) :
2013-03-07 02:54:12 +00:00
self . template_name = " recommended.html "
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 ' ) :
2013-03-07 02:54:12 +00:00
return models . Work . objects . exclude ( num_wishes = 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 ' )
2012-07-21 20:26:16 +00:00
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 )
2013-03-05 21:18:54 +00:00
context [ ' facet ' ] = self . kwargs . get ( ' facet ' , ' ' )
2013-03-07 02:54:12 +00:00
works_unglued = qs . exclude ( editions__ebooks__isnull = True ) . distinct ( ) | qs . filter ( campaigns__status = ' SUCCESSFUL ' ) . distinct ( )
2013-06-27 16:00:47 +00:00
context [ ' works_unglued ' ] = works_unglued [ : self . max_works ]
2013-03-05 21:18:54 +00:00
context [ ' works_active ' ] = qs . filter ( campaigns__status = ' ACTIVE ' ) . distinct ( ) [ : self . max_works ]
context [ ' works_wished ' ] = qs . exclude ( editions__ebooks__isnull = False ) . exclude ( campaigns__status = ' ACTIVE ' ) . exclude ( campaigns__status = ' SUCCESSFUL ' ) . distinct ( ) [ : self . max_works ]
2013-05-16 15:43:25 +00:00
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
2012-05-08 18:28:06 +00:00
2013-05-17 15:30:22 +00:00
if counts [ ' unglueing ' ] :
2013-05-16 15:43:25 +00:00
context [ ' activetab ' ] = " #2 "
2013-05-17 15:30:22 +00:00
elif counts [ ' unglued ' ] :
2013-05-16 15:43:25 +00:00
context [ ' activetab ' ] = " #1 "
else :
context [ ' activetab ' ] = " #3 "
2011-12-03 00:29:23 +00:00
return context
2012-01-15 21:48:26 +00:00
2013-03-26 03:41:19 +00:00
class ByPubView ( WorkListView ) :
2013-03-05 21:18:54 +00:00
template_name = " bypub_list.html "
context_object_name = " work_list "
2013-03-26 18:53:48 +00:00
max_works = 100000
publisher_name = None
publisher = None
2013-03-26 03:41:19 +00:00
def get_publisher_name ( self ) :
self . publisher_name = get_object_or_404 ( models . PublisherName , id = self . kwargs [ ' pubname ' ] )
2013-03-26 18:53:48 +00:00
self . set_publisher ( )
def set_publisher ( self ) :
2013-03-27 16:22:30 +00:00
if self . publisher_name . key_publisher . count ( ) :
2013-03-26 18:53:48 +00:00
self . publisher = self . publisher_name . key_publisher . all ( ) [ 0 ]
elif self . publisher_name . publisher :
self . publisher = self . publisher_name . publisher
self . publisher_name = self . publisher . name
2013-03-26 03:41:19 +00:00
2013-03-05 21:18:54 +00:00
def get_queryset_all ( self ) :
facet = self . kwargs . get ( ' facet ' , ' ' )
2013-03-26 03:41:19 +00:00
self . get_publisher_name ( )
objects = models . Work . objects . filter ( editions__publisher_name__id = self . publisher_name . id ) . distinct ( )
2013-03-05 21:18:54 +00:00
if ( facet == ' popular ' ) :
return objects . order_by ( ' -num_wishes ' , ' id ' )
elif ( facet == ' pubdate ' ) :
2013-03-07 02:54:12 +00:00
return objects . order_by ( ' -editions__publication_date ' ) # turns out this messes up distinct, and MySQL doesn't support DISTINCT ON
2013-03-05 21:18:54 +00:00
elif ( facet == ' new ' ) :
return objects . filter ( num_wishes__gt = 0 ) . order_by ( ' -created ' , ' -num_wishes ' , ' id ' )
else :
return objects . order_by ( ' title ' , ' id ' )
def get_context_data ( self , * * kwargs ) :
2013-03-26 03:41:19 +00:00
context = super ( ByPubView , self ) . get_context_data ( * * kwargs )
context [ ' pubname ' ] = self . publisher_name
2013-03-26 18:53:48 +00:00
context [ ' publisher ' ] = self . publisher
2013-03-05 21:18:54 +00:00
return context
2013-03-26 03:41:19 +00:00
class ByPubListView ( ByPubView ) :
def get_publisher_name ( self ) :
self . publisher_name = get_object_or_404 ( models . PublisherName , name = self . kwargs [ ' pubname ' ] )
2013-03-26 18:53:48 +00:00
self . set_publisher ( )
2013-03-26 03:41:19 +00:00
2012-07-21 20:26:16 +00:00
class UngluedListView ( FilterableListView ) :
2012-01-15 21:48:26 +00:00
template_name = " unglued_list.html "
context_object_name = " work_list "
2012-07-21 20:26:16 +00:00
def get_queryset_all ( self ) :
2012-01-15 21:48:26 +00:00
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 ' )
2013-02-04 15:09:08 +00:00
elif ( facet == ' cc ' or facet == ' creativecommons ' ) :
# assumes all ebooks have a PD or CC license. compare rights_badge property
2013-02-04 18:32:21 +00:00
return models . Work . objects . filter (
editions__ebooks__isnull = False ,
editions__ebooks__rights__in = [ ' CC BY ' , ' CC BY-NC-SA ' , ' CC BY-NC-ND ' , ' CC BY-NC ' , ' CC BY-ND ' , ' CC BY-SA ' ]
) . distinct ( ) . order_by ( ' -num_wishes ' )
2013-02-04 15:09:08 +00:00
elif ( facet == ' pd ' or facet == ' publicdomain ' ) :
2013-02-04 18:32:21 +00:00
return models . Work . objects . filter (
editions__ebooks__isnull = False ,
editions__ebooks__rights__in = [ ' PD-US ' , ' CC0 ' , ' ' ]
) . distinct ( ) . order_by ( ' -num_wishes ' )
2013-02-06 23:14:56 +00:00
else :
#(facet == '' or facet == 'unglued' or facet is other)
return models . Work . objects . filter ( campaigns__status = " SUCCESSFUL " ) . distinct ( ) . order_by ( ' -campaigns__deadline ' )
2012-01-15 21:48:26 +00:00
def get_context_data ( self , * * kwargs ) :
2013-02-04 15:09:08 +00:00
context = super ( UngluedListView , self ) . get_context_data ( * * kwargs )
qs = self . get_queryset ( )
context [ ' ungluers ' ] = userlists . work_list_users ( qs , 5 )
facet = self . kwargs [ ' facet ' ]
context [ ' facet ' ] = facet
if facet == ' cc ' or facet == ' creativecommons ' :
context [ ' activetab ' ] = " #2 "
elif facet == ' pd ' or facet == ' publicdomain ' :
context [ ' activetab ' ] = " #3 "
else :
2012-03-02 14:40:10 +00:00
context [ ' activetab ' ] = " #1 "
2013-02-04 15:09:08 +00:00
return context
2012-01-15 21:48:26 +00:00
2012-07-21 20:26:16 +00:00
class CampaignListView ( FilterableListView ) :
2011-12-01 18:17:33 +00:00
template_name = " campaign_list.html "
context_object_name = " campaign_list "
model = models . Campaign
2012-07-21 20:26:16 +00:00
def get_queryset_all ( self ) :
2011-12-01 18:17:33 +00:00
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 ' )
2013-06-05 19:08:29 +00:00
elif ( facet == ' soon ' ) :
return models . Campaign . objects . filter ( status = ' INITIALIZED ' ) . order_by ( ' -work__num_wishes ' )
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
2012-08-07 18:12:50 +00:00
2013-04-16 20:46:25 +00:00
@login_required
def split_work ( request , work_id ) :
if not request . user . is_staff :
return render ( request , " admins_only.html " )
work = get_object_or_404 ( models . Work , id = work_id )
EditionFormSet = inlineformset_factory ( models . Work , models . Edition , fields = ( ) , extra = 0 )
if request . method == " POST " :
formset = EditionFormSet ( data = request . POST , instance = work )
if formset . is_valid ( ) :
for form in formset . deleted_forms :
detach_edition ( form . instance )
formset = EditionFormSet ( instance = work )
return render ( request , " split.html " , { " work " : work , " formset " : formset , } )
2012-12-13 03:35:35 +00:00
class MergeView ( FormView ) :
template_name = " merge.html "
work = None
def dispatch ( self , request , * args , * * kwargs ) :
if not request . user . is_staff :
return render ( request , " admins_only.html " )
else :
return super ( MergeView , self ) . dispatch ( request , * args , * * kwargs )
def get_context_data ( self , * * kwargs ) :
context = super ( MergeView , self ) . get_context_data ( * * kwargs )
context [ ' work ' ] = self . work
return context
def get_form_class ( self ) :
if self . request . method == ' POST ' and self . request . POST . has_key ( ' confirm_merge_works ' ) :
return WorkForm
else :
return OtherWorkForm
def get_form_kwargs ( self ) :
self . work = get_object_or_404 ( models . Work , id = self . kwargs [ " work_id " ] )
form_kwargs = { ' work ' : self . work }
if self . request . method == ' POST ' :
form_kwargs . update ( { ' data ' : self . request . POST } )
return form_kwargs
def form_valid ( self , form ) :
other_work = form . cleaned_data [ ' other_work ' ]
context = self . get_context_data ( )
if self . request . POST . has_key ( ' confirm_merge_works ' ) :
context [ ' old_work_id ' ] = other_work . id
merge_works ( self . work , other_work , self . request . user )
context [ ' merge_complete ' ] = True
else :
context [ ' form ' ] = WorkForm ( initial = { ' other_work ' : other_work } )
context [ ' other_work ' ] = other_work
return render ( self . request , self . template_name , context )
2012-08-07 18:12:50 +00:00
class DonationView ( TemplateView ) :
template_name = " donation.html "
def get ( self , request , * args , * * kwargs ) :
2012-08-14 01:00:28 +00:00
context = self . get_context_data ( )
context [ ' transfer_form ' ] = getTransferCreditForm ( self . request . user . credit . available )
return self . render_to_response ( context )
2012-08-07 18:12:50 +00:00
def post ( self , request , * args , * * kwargs ) :
2012-08-14 01:00:28 +00:00
context = self . get_context_data ( )
transfer_form = getTransferCreditForm ( self . request . user . credit . available , data = self . request . POST )
if transfer_form . is_valid ( ) :
if self . request . user . credit . transfer_to ( transfer_form . cleaned_data [ ' recipient ' ] , transfer_form . cleaned_data [ ' amount ' ] ) :
#successful transfer
context [ ' transfer_message ' ] = ' Your transfer has been successfully executed. '
context [ ' recipient ' ] = transfer_form . cleaned_data [ ' recipient ' ]
context [ ' transfer_amount ' ] = transfer_form . cleaned_data [ ' amount ' ]
context [ ' transfer_form ' ] = getTransferCreditForm ( self . request . user . credit . available )
else :
#unsuccessful transfer
context [ ' transfer_message ' ] = ' Your transfer was not successful. '
context [ ' transfer_form ' ] = transfer_form
else :
#not valid
context [ ' transfer_form ' ] = transfer_form
return self . render_to_response ( context )
2012-08-07 18:12:50 +00:00
def get_context_data ( self , * args , * * kwargs ) :
2012-09-21 21:15:30 +00:00
context = { ' user ' : self . request . user , ' nonprofit ' : settings . NONPROFIT }
context [ ' donate_form ' ] = DonateForm ( initial = { ' username ' : self . request . user . username } )
2012-08-07 18:12:50 +00:00
return context
2013-06-27 17:10:33 +00:00
2011-11-28 23:39:06 +00:00
class PledgeView ( FormView ) :
2013-08-16 19:49:44 +00:00
action = " pledge "
2011-11-28 23:39:06 +00:00
template_name = " pledge.html "
form_class = CampaignPledgeForm
2012-08-31 07:16:04 +00:00
transaction = None
campaign = None
work = None
premiums = None
data = None
2012-03-15 21:54:38 +00:00
2012-09-07 20:13:53 +00:00
def get_preapproval_amount ( self ) :
2011-11-30 02:02:51 +00:00
preapproval_amount = self . request . REQUEST . get ( ' preapproval_amount ' , None )
2012-09-07 20:13:53 +00:00
if preapproval_amount :
return preapproval_amount
premium_id = self . request . REQUEST . get ( ' premium_id ' , None )
if premium_id != 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-09-07 21:11:25 +00:00
if self . transaction :
if preapproval_amount :
preapproval_amount = preapproval_amount if preapproval_amount > self . transaction . amount else self . transaction . amount
else :
preapproval_amount = self . transaction . amount
2012-09-07 20:13:53 +00:00
return preapproval_amount
2012-08-31 07:16:04 +00:00
def get_form_kwargs ( self ) :
2012-09-19 21:30:47 +00:00
2012-05-13 19:18:48 +00:00
assert self . request . user . is_authenticated ( )
2012-08-31 07:16:04 +00:00
self . work = get_object_or_404 ( models . Work , id = self . kwargs [ " work_id " ] )
2012-03-15 21:54:38 +00:00
2012-06-21 17:16:51 +00:00
# if there is no campaign or if campaign is not active, we should raise an error
2012-05-01 13:56:19 +00:00
try :
2012-08-31 07:16:04 +00:00
self . campaign = self . work . last_campaign ( )
# TODO need to sort the premiums
self . premiums = self . campaign . custom_premiums ( ) | models . Premium . objects . filter ( id = 150 )
# Campaign must be ACTIVE
assert self . campaign . status == ' ACTIVE '
except Exception , e :
raise e
2012-05-01 13:56:19 +00:00
2012-08-31 07:16:04 +00:00
transactions = self . campaign . transactions ( ) . filter ( user = self . request . user , status = TRANSACTION_STATUS_ACTIVE , type = PAYMENT_TYPE_AUTHORIZATION )
2012-10-14 15:33:13 +00:00
premium_id = self . request . REQUEST . get ( ' premium_id ' , 150 )
2012-08-31 07:16:04 +00:00
if transactions . count ( ) == 0 :
2012-10-18 18:13:42 +00:00
ack_name = self . request . user . profile . ack_name
2012-08-31 07:16:04 +00:00
ack_dedication = ' '
2012-10-18 18:13:42 +00:00
anonymous = self . request . user . profile . anon_pref
2012-08-31 07:16:04 +00:00
else :
2012-09-07 21:11:25 +00:00
self . transaction = transactions [ 0 ]
2012-10-15 15:39:09 +00:00
if premium_id == 150 and self . transaction . premium is not None :
2012-08-31 07:16:04 +00:00
premium_id = self . transaction . premium . id
2013-08-18 19:21:55 +00:00
if self . transaction . extra :
ack_name = self . transaction . extra . get ( ' ack_name ' , self . request . user . profile . ack_name )
ack_dedication = self . transaction . extra . get ( ' ack_dedication ' , ' ' )
2012-10-23 13:37:00 +00:00
else :
ack_name = self . request . user . profile . ack_name
2013-08-18 19:21:55 +00:00
ack_dedication = ' '
2012-08-31 07:16:04 +00:00
anonymous = self . transaction . anonymous
2012-09-07 20:13:53 +00:00
2012-09-07 21:11:25 +00:00
self . data = { ' preapproval_amount ' : self . get_preapproval_amount ( ) , ' premium_id ' : premium_id ,
' ack_name ' : ack_name , ' ack_dedication ' : ack_dedication , ' anonymous ' : anonymous }
2012-08-31 07:16:04 +00:00
if self . request . method == ' POST ' :
self . data . update ( self . request . POST . dict ( ) )
2012-10-13 02:24:58 +00:00
if not self . request . POST . has_key ( ' anonymous ' ) :
del self . data [ ' anonymous ' ]
2012-10-13 03:43:51 +00:00
if not self . request . POST . has_key ( ' ack_name ' ) :
del self . data [ ' ack_name ' ]
if not self . request . POST . has_key ( ' ack_dedication ' ) :
del self . data [ ' ack_dedication ' ]
2012-08-31 07:16:04 +00:00
return { ' data ' : self . data }
else :
2012-09-07 21:11:25 +00:00
return { ' initial ' : self . data }
2011-11-28 23:39:06 +00:00
2012-08-31 07:16:04 +00:00
def get_context_data ( self , * * kwargs ) :
""" set up the pledge page """
2012-03-15 21:54:38 +00:00
2012-08-31 07:16:04 +00:00
context = super ( PledgeView , self ) . get_context_data ( * * kwargs )
2012-10-02 13:18:44 +00:00
context [ ' nonprofit ' ] = settings . NONPROFIT
2012-08-31 07:16:04 +00:00
2012-05-25 22:44:28 +00:00
context . update ( {
2012-08-31 07:16:04 +00:00
' work ' : self . work ,
' campaign ' : self . campaign ,
' premiums ' : self . premiums ,
' premium_id ' : self . data [ ' premium_id ' ] ,
' faqmenu ' : ' modify ' if self . transaction else ' pledge ' ,
' transaction ' : self . transaction ,
' tid ' : self . transaction . id if self . transaction else None ,
2013-02-07 20:25:14 +00:00
' cover_width ' : cover_width ( self . work )
2012-08-31 07:16:04 +00:00
} )
2012-05-13 19:18:48 +00:00
2011-11-28 23:39:06 +00:00
return context
def form_valid ( self , form ) :
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
2012-08-31 07:16:04 +00:00
p = PaymentManager ( )
if self . transaction :
# modifying the transaction...
assert self . transaction . type == PAYMENT_TYPE_AUTHORIZATION and self . transaction . status == TRANSACTION_STATUS_ACTIVE
status , url = p . modify_transaction ( self . transaction , form . cleaned_data [ " preapproval_amount " ] ,
2013-08-16 19:49:44 +00:00
paymentReason = " Unglue.it %s for %s " % ( self . action , self . campaign . name ) ,
pledge_extra = form . trans_extra
2012-08-31 07:16:04 +00:00
)
logger . info ( " status: {0} , url: {1} " . format ( status , url ) )
2012-01-10 20:16:04 +00:00
2012-08-31 07:16:04 +00:00
if status and url is not None :
logger . info ( " PledgeView (Modify): " + url )
return HttpResponseRedirect ( url )
elif status and url is None :
2012-09-07 21:48:48 +00:00
return HttpResponseRedirect ( " {0} ?tid= {1} " . format ( reverse ( ' pledge_modified ' ) , self . transaction . id ) )
2012-08-31 07:16:04 +00:00
else :
return HttpResponse ( " No modification made " )
2011-11-28 23:39:06 +00:00
else :
2013-08-16 19:49:44 +00:00
t , url = p . process_transaction ( ' USD ' , form . amount ( ) ,
2012-09-19 00:01:07 +00:00
host = PAYMENT_HOST_NONE ,
2012-08-31 07:16:04 +00:00
campaign = self . campaign ,
user = self . request . user ,
paymentReason = " Unglue.it Pledge for {0} " . format ( self . campaign . name ) ,
2013-08-16 19:49:44 +00:00
pledge_extra = form . trans_extra
2012-08-31 07:16:04 +00:00
)
if url :
logger . info ( " PledgeView url: " + url )
return HttpResponseRedirect ( url )
else :
logger . error ( " Attempt to produce transaction id {0} failed " . format ( t . id ) )
return HttpResponse ( " Our attempt to enable your transaction failed. We have logged this error. " )
2012-01-09 17:36:03 +00:00
2013-06-27 17:10:33 +00:00
class PurchaseView ( PledgeView ) :
2013-08-16 19:49:44 +00:00
template_name = " purchase.html "
form_class = CampaignPurchaseForm
action = " purchase "
def get_context_data ( self , * * kwargs ) :
context = super ( PledgeView , self ) . get_context_data ( * * kwargs )
context . update ( {
' work ' : self . work ,
' campaign ' : self . campaign ,
' faqmenu ' : ' purchase ' ,
' transaction ' : self . transaction ,
' tid ' : self . transaction . id if self . transaction else None ,
' cover_width ' : cover_width ( self . work )
} )
return context
2013-06-27 17:10:33 +00:00
2012-09-06 05:01:17 +00:00
class FundPledgeView ( FormView ) :
template_name = " fund_the_pledge.html "
form_class = CCForm
transaction = None
2012-03-19 23:32:37 +00:00
2012-09-06 05:01:17 +00:00
def get_form_kwargs ( self ) :
2012-09-10 20:17:30 +00:00
kwargs = super ( FundPledgeView , self ) . get_form_kwargs ( )
2012-03-19 23:32:37 +00:00
assert self . request . user . is_authenticated ( )
2012-09-06 05:01:17 +00:00
if self . transaction is None :
self . transaction = get_object_or_404 ( Transaction , id = self . kwargs [ " t_id " ] )
2012-10-13 17:45:46 +00:00
2012-09-10 20:17:30 +00:00
if kwargs . has_key ( ' data ' ) :
data = kwargs [ ' data ' ] . copy ( )
2012-03-21 21:53:33 +00:00
else :
2012-09-10 20:17:30 +00:00
data = { }
2012-03-19 23:32:37 +00:00
2012-09-10 20:17:30 +00:00
data . update (
{ ' preapproval_amount ' : self . transaction . max_amount ,
2012-09-06 05:01:17 +00:00
' username ' : self . request . user . username ,
' work_id ' : self . transaction . campaign . work . id ,
2012-09-10 20:17:30 +00:00
' title ' : self . transaction . campaign . work . title }
)
2012-03-19 23:32:37 +00:00
2012-09-10 20:17:30 +00:00
kwargs [ ' data ' ] = data
2012-03-19 23:32:37 +00:00
2012-09-10 20:17:30 +00:00
return kwargs
2012-09-06 05:01:17 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( FundPledgeView , self ) . get_context_data ( * * kwargs )
2012-09-06 20:55:32 +00:00
context [ ' modified ' ] = self . transaction . status == TRANSACTION_STATUS_MODIFIED
2012-09-06 05:01:17 +00:00
context [ ' preapproval_amount ' ] = self . transaction . max_amount
2012-09-06 20:55:32 +00:00
context [ ' needed ' ] = self . transaction . max_amount - self . request . user . credit . available
2012-09-06 05:01:17 +00:00
context [ ' transaction ' ] = self . transaction
context [ ' nonprofit ' ] = settings . NONPROFIT
2012-09-11 22:17:37 +00:00
context [ ' STRIPE_PK ' ] = stripelib . STRIPE_PK
2012-09-06 20:55:32 +00:00
# note that get_form_kwargs() will already have been called once
2012-09-07 13:39:36 +00:00
donate_args = self . get_form_kwargs ( )
donate_args [ ' data ' ] [ ' preapproval_amount ' ] = context [ ' needed ' ]
context [ ' donate_form ' ] = DonateForm ( * * donate_args )
2012-03-19 23:32:37 +00:00
return context
2012-09-10 20:17:30 +00:00
def post ( self , request , * args , * * kwargs ) :
logger . info ( ' request.POST: {0} ' . format ( request . POST ) )
return super ( FundPledgeView , self ) . post ( request , * args , * * kwargs )
2012-03-22 19:09:13 +00:00
2012-03-19 23:32:37 +00:00
def form_valid ( self , form ) :
2012-09-11 22:17:37 +00:00
""" note desire to pledge; make sure there is a credit card to charge """
2012-09-11 22:53:39 +00:00
2012-10-13 17:40:36 +00:00
if self . transaction . user . id != self . request . user . id :
# trouble!
2012-10-15 02:47:40 +00:00
return render ( self . request , " pledge_user_error.html " , { ' transaction ' : self . transaction } )
2012-09-11 22:53:39 +00:00
2012-09-22 00:40:33 +00:00
p = PaymentManager ( )
2012-10-13 17:45:46 +00:00
# if the user has active account, use it. Otherwise...
if not self . request . user . profile . account :
stripe_token = form . cleaned_data [ " stripe_token " ]
# if we get a stripe_token, create a new stripe account for the user
if stripe_token :
try :
p . make_account ( user = self . request . user , host = settings . PAYMENT_PROCESSOR , token = stripe_token )
except baseprocessor . ProcessorError as e :
2012-11-14 19:51:32 +00:00
return render ( self . request , " pledge_card_error.html " , { ' transaction ' : self . transaction , ' exception ' : e } )
else : # empty token
e = baseprocessor . ProcessorError ( " Empty token " )
return render ( self . request , " pledge_card_error.html " , { ' transaction ' : self . transaction , ' exception ' : e } )
2012-10-13 17:45:46 +00:00
self . transaction . host = settings . PAYMENT_PROCESSOR
preapproval_amount = form . cleaned_data [ " preapproval_amount " ]
2012-09-24 23:29:20 +00:00
# with the Account in hand, now authorize transaction
2012-10-13 17:38:39 +00:00
self . transaction . max_amount = preapproval_amount
2012-10-13 17:45:46 +00:00
t , url = p . authorize ( self . transaction )
2012-09-22 00:40:33 +00:00
logger . info ( " t, url: {0} {1} " . format ( t , url ) )
2012-09-25 18:52:56 +00:00
# redirecting user to pledge_complete on successful preapproval (in the case of stripe)
if url is not None :
return HttpResponseRedirect ( url )
2012-10-13 04:46:34 +00:00
else :
2012-10-15 02:47:40 +00:00
return render ( self . request , " pledge_card_error.html " , { ' transaction ' : self . transaction } )
2012-03-19 23:32:37 +00:00
2012-09-06 05:01:17 +00:00
class NonprofitCampaign ( FormView ) :
template_name = " nonprofit.html "
form_class = CCForm
def get_context_data ( self , * * kwargs ) :
context = super ( NonprofitCampaign , self ) . get_context_data ( * * kwargs )
context [ ' nonprofit ' ] = settings . NONPROFIT
context [ ' get ' ] = self . request . GET
return context
def get_form_kwargs ( self ) :
if self . request . method == ' POST ' :
return { ' data ' : self . request . POST }
2012-03-19 23:32:37 +00:00
else :
2012-09-06 05:01:17 +00:00
return { ' initial ' : self . request . GET }
2012-03-19 23:32:37 +00:00
2012-09-06 05:01:17 +00:00
2012-03-19 23:32:37 +00:00
2012-09-06 05:01:17 +00:00
def form_valid ( self , form ) :
username = form . cleaned_data [ ' username ' ]
forward = { ' username ' : username }
forward [ ' work_id ' ] = form . cleaned_data [ ' work_id ' ]
2012-09-06 15:36:13 +00:00
amount = form . cleaned_data [ ' preapproval_amount ' ]
forward [ ' cents ' ] = int ( 100 * ( amount - int ( amount ) ) )
forward [ ' amount ' ] = int ( amount )
2012-09-06 05:01:17 +00:00
forward [ ' sent ' ] = Sent . objects . create ( user = username , amount = form . cleaned_data [ ' preapproval_amount ' ] ) . pk
token = signing . dumps ( forward )
2013-03-09 18:29:03 +00:00
return HttpResponseRedirect ( settings . BASE_URL_SECURE + reverse ( ' donation_credit ' , kwargs = { ' token ' : token } ) )
2012-07-10 20:36:32 +00:00
2012-09-06 05:01:17 +00:00
class DonationCredit ( TemplateView ) :
template_name = " donation_credit.html "
2012-07-10 20:36:32 +00:00
2012-09-06 05:01:17 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( DonationCredit , self ) . get_context_data ( * * kwargs )
2012-09-06 18:04:47 +00:00
context [ ' faqmenu ' ] = " donation "
2012-09-06 20:55:32 +00:00
context [ ' nonprofit ' ] = settings . NONPROFIT
2012-09-06 05:01:17 +00:00
try :
envelope = signing . loads ( kwargs [ ' token ' ] )
context [ ' envelope ' ] = envelope
except signing . BadSignature :
self . template_name = " donation_error.html "
return context
try :
work = models . Work . objects . get ( id = envelope [ ' work_id ' ] )
campaign = work . last_campaign ( )
except models . Work . DoesNotExist :
campaign = None
context [ ' work ' ] = work
try :
user = User . objects . get ( username = envelope [ ' username ' ] )
except User . DoesNotExist :
self . template_name = " donation_user_error.html "
context [ ' error ' ] = ' user does not exist '
return context
if user != self . request . user :
self . template_name = " donation_user_error.html "
context [ ' error ' ] = ' wrong user logged in '
return context
try :
# check token not used
CreditLog . objects . get ( sent = envelope [ ' sent ' ] )
context [ ' error ' ] = ' credit already registered '
return context
except CreditLog . DoesNotExist :
#not used yet!
2012-09-06 15:36:13 +00:00
amount = envelope [ ' amount ' ] + envelope [ ' cents ' ] / D ( 100 )
CreditLog . objects . create ( user = user , amount = amount , action = ' deposit ' , sent = envelope [ ' sent ' ] )
2012-09-06 20:55:32 +00:00
ts = Transaction . objects . filter ( user = user , campaign = campaign , status = TRANSACTION_STATUS_NONE ) . order_by ( ' -pk ' )
if ts . count ( ) == 0 :
ts = Transaction . objects . filter ( user = user , campaign = campaign , status = TRANSACTION_STATUS_MODIFIED ) . order_by ( ' -pk ' )
2012-09-06 05:01:17 +00:00
if ts . count ( ) > 0 :
t = ts [ 0 ]
2012-09-06 15:36:13 +00:00
credit_transaction ( t , user , amount )
2012-09-06 05:01:17 +00:00
for t in ts [ 1 : ] :
t . status = TRANSACTION_STATUS_CANCELED
t . save ( )
context [ ' transaction ' ] = t
return context
else :
2012-09-06 15:36:13 +00:00
user . credit . add_to_balance ( amount )
2012-09-06 05:01:17 +00:00
return context
2012-07-10 20:36:32 +00:00
class PledgeRechargeView ( TemplateView ) :
"""
a view to allow for recharge of a transaction for failed transactions or ones with errors
"""
template_name = " pledge_recharge.html "
def get_context_data ( self , * * kwargs ) :
2012-07-12 02:51:36 +00:00
context = super ( PledgeRechargeView , self ) . get_context_data ( * * kwargs )
2012-07-10 20:36:32 +00:00
2012-08-31 07:16:04 +00:00
# the following should be true since PledgeView.as_view is wrapped in login_required
2012-07-10 20:36:32 +00:00
assert self . request . user . is_authenticated ( )
user = self . request . user
work = get_object_or_404 ( models . Work , id = self . kwargs [ " work_id " ] )
2012-07-13 17:17:51 +00:00
campaign = work . last_campaign ( )
if campaign is None :
return Http404
transaction = campaign . transaction_to_recharge ( user )
# calculate a URL to do a preapproval -- in the future, we may want to do a straight up payment
2012-07-13 22:55:41 +00:00
return_url = None
nevermind_url = None
2012-07-10 20:36:32 +00:00
2012-07-13 22:55:41 +00:00
if transaction is not None :
2012-09-07 13:46:38 +00:00
# the recipients of this authorization is not specified here but rather by the PaymentManager.
2012-07-13 22:55:41 +00:00
paymentReason = " Unglue.it Recharge for {0} " . format ( campaign . name )
2012-08-31 07:16:04 +00:00
p = PaymentManager ( )
2012-09-07 13:46:38 +00:00
t , url = p . authorize ( transaction , return_url = return_url , paymentReason = paymentReason )
2012-07-13 22:55:41 +00:00
logger . info ( " Recharge url: {0} " . format ( url ) )
else :
url = None
2012-07-10 20:36:32 +00:00
context . update ( {
' work ' : work ,
2012-07-13 17:17:51 +00:00
' transaction ' : transaction ,
2012-07-13 22:55:41 +00:00
' payment_processor ' : transaction . host if transaction is not None else None ,
' recharge_url ' : url
2012-07-10 20:36:32 +00:00
} )
return context
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
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
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.
try :
2012-09-07 21:48:48 +00:00
if user . id != transaction . user . id :
2012-03-19 18:46:41 +00:00
# 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
2012-10-16 14:41:30 +00:00
# fire add-wishlist notification if needed
2012-09-07 21:48:48 +00:00
if user is not None and correct_transaction_type and ( campaign is not None ) and ( work is not None ) :
2012-03-16 20:03:38 +00:00
# ok to overwrite Wishes.source?
2012-10-16 15:36:51 +00:00
user . wishlist . add_work ( work , ' pledging ' , notify = True )
2012-03-26 19:26:47 +00:00
2012-05-01 17:49:23 +00:00
worklist = slideshow ( 8 )
works = worklist [ : 4 ]
works2 = worklist [ 4 : 8 ]
2012-03-26 19:26:47 +00:00
2012-01-11 01:15:39 +00:00
context [ " transaction " ] = transaction
context [ " work " ] = work
context [ " campaign " ] = campaign
2012-02-21 14:24:23 +00:00
context [ " faqmenu " ] = " complete "
2012-03-26 19:26:47 +00:00
context [ " works " ] = works
2012-05-13 02:42:09 +00:00
context [ " works2 " ] = works2
2012-05-14 20:56:36 +00:00
context [ " site " ] = Site . objects . get_current ( )
2012-01-11 01:15:39 +00:00
return context
2012-09-07 21:48:48 +00:00
class PledgeModifiedView ( PledgeCompleteView ) :
def get_context_data ( self ) :
context = super ( PledgeModifiedView , self ) . get_context_data ( )
context [ ' modified ' ] = True
return context
2012-01-09 17:36:03 +00:00
2012-05-21 14:56:18 +00:00
class PledgeCancelView ( FormView ) :
""" A view for allowing a user to cancel the active transaction for specified campaign """
2012-01-09 17:36:03 +00:00
template_name = " pledge_cancel.html "
2012-05-21 14:56:18 +00:00
form_class = PledgeCancelForm
2012-01-09 17:36:03 +00:00
2012-05-21 14:56:18 +00:00
def get_context_data ( self , * * kwargs ) :
context = super ( PledgeCancelView , self ) . get_context_data ( * * kwargs )
2012-05-18 23:59:48 +00:00
2012-05-23 14:22:48 +00:00
# initialize error to be None
context [ " error " ] = None
2012-05-18 23:59:48 +00:00
2012-05-21 14:56:18 +00:00
# the following should be true since PledgeCancelView.as_view is wrapped in login_required
2012-05-23 14:22:48 +00:00
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
2012-05-25 01:47:50 +00:00
context [ " error " ] = " You are not logged in. "
2012-05-23 14:22:48 +00:00
return context
2012-05-18 23:59:48 +00:00
2012-05-21 14:56:18 +00:00
campaign = get_object_or_404 ( models . Campaign , id = self . kwargs [ " campaign_id " ] )
2012-05-23 14:22:48 +00:00
if campaign . status != ' ACTIVE ' :
context [ " error " ] = " {0} is not an active campaign " . format ( campaign )
return context
2012-05-21 14:56:18 +00:00
work = campaign . work
transactions = campaign . transactions ( ) . filter ( user = user , status = TRANSACTION_STATUS_ACTIVE )
2012-05-23 14:22:48 +00:00
if transactions . count ( ) < 1 :
2012-05-25 01:47:50 +00:00
context [ " error " ] = " You don ' t have an active transaction for this campaign. "
2012-05-23 14:22:48 +00:00
return context
elif transactions . count ( ) > 1 :
2012-05-25 01:47:50 +00:00
logger . error ( " User {0} has {1} active transactions for campaign id {2} " . format ( user , transactions . count ( ) , campaign . id ) )
2012-05-23 14:22:48 +00:00
context [ " error " ] = " You have {0} active transactions for this campaign " . format ( transactions . count ( ) )
return context
2012-05-21 14:56:18 +00:00
transaction = transactions [ 0 ]
2012-05-23 14:22:48 +00:00
if transaction . type != PAYMENT_TYPE_AUTHORIZATION :
2012-05-25 01:47:50 +00:00
logger . error ( " Transaction id {0} transaction type, which should be {1} , is actually {2} " . format ( transaction . id , PAYMENT_TYPE_AUTHORIZATION , transaction . type ) )
2012-05-23 14:22:48 +00:00
context [ " error " ] = " Your transaction type, which should be {0} , is actually {1} " . format ( PAYMENT_TYPE_AUTHORIZATION , transaction . type )
return context
# we've located the transaction, work, and campaign referenced in the view
2012-05-18 23:59:48 +00:00
context [ " transaction " ] = transaction
context [ " work " ] = work
context [ " campaign " ] = campaign
context [ " faqmenu " ] = " cancel "
return context
2012-05-23 14:22:48 +00:00
def form_valid ( self , form ) :
# check that user does, in fact, have an active transaction for specified campaign
logger . info ( " arrived at pledge_cancel form_valid " )
# pull campaign_id from form, not from URI as we do from GET
campaign_id = self . request . REQUEST . get ( ' campaign_id ' )
2012-05-25 01:47:50 +00:00
# this following logic should be extraneous.
if self . request . user . is_authenticated ( ) :
user = self . request . user
else :
return HttpResponse ( " You need to be logged in. " )
2012-05-23 14:22:48 +00:00
try :
2012-05-23 16:12:21 +00:00
# look up the specified campaign and attempt to pull up the appropriate transaction
# i.e., the transaction actually belongs to user, that the transaction is active
2012-05-23 14:22:48 +00:00
campaign = get_object_or_404 ( models . Campaign , id = self . kwargs [ " campaign_id " ] , status = ' ACTIVE ' )
transaction = campaign . transaction_set . get ( user = user , status = TRANSACTION_STATUS_ACTIVE ,
type = PAYMENT_TYPE_AUTHORIZATION )
2012-05-23 16:12:21 +00:00
# attempt to cancel the transaction and redirect to the Work page if cancel is successful
2012-05-23 14:22:48 +00:00
# here's a place that would be nice to use https://docs.djangoproject.com/en/dev/ref/contrib/messages/
2012-05-23 16:12:21 +00:00
# to display the success or failure of the cancel operation as a popup in the context of the work page
2012-05-23 14:22:48 +00:00
p = PaymentManager ( )
result = p . cancel_transaction ( transaction )
2012-05-25 01:47:50 +00:00
# put a notification here for pledge cancellation?
2012-05-23 16:12:21 +00:00
if result :
# Now if we redirect the user to the Work page and the IPN hasn't arrived, the status of the
# transaction might be out of date. Let's try an explicit polling of the transaction result before redirecting
# We might want to remove this in a production system
if settings . DEBUG :
update_status = p . update_preapproval ( transaction )
2012-06-15 20:14:26 +00:00
# send a notice out that the transaction has been canceled -- leverage the pledge_modify notice for now
# BUGBUG: should have a pledge cancel notice actually since I think it's different
from regluit . payment . signals import pledge_modified
pledge_modified . send ( sender = self , transaction = transaction , up_or_down = " canceled " )
logger . info ( " pledge_modified notice for cancellation: sender {0} , transaction {1} " . format ( self , transaction ) )
2012-05-23 16:12:21 +00:00
return HttpResponseRedirect ( reverse ( ' work ' , kwargs = { ' work_id ' : campaign . work . id } ) )
else :
2012-05-25 01:47:50 +00:00
logger . error ( " Attempt to cancel transaction id {0} failed " . format ( transaction . id ) )
return HttpResponse ( " Our attempt to cancel your transaction failed. We have logged this error. " )
except Exception , e :
logger . error ( " Exception from attempt to cancel pledge for campaign id {0} for username {1} : {2} " . format ( campaign_id , user . username , e ) )
2012-09-07 13:46:38 +00:00
return HttpResponse ( " Sorry, something went wrong in canceling your campaign pledge. We have logged this error. " )
2011-12-03 00:37:27 +00:00
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-10-07 14:58:59 +00:00
if not models . Claim . objects . filter ( work = form . cleaned_data [ ' work ' ] , rights_holder = form . cleaned_data [ ' rights_holder ' ] ) . exclude ( status = ' release ' ) . count ( ) :
2011-11-16 05:22:22 +00:00
form . save ( )
2012-10-07 14:58:59 +00:00
return HttpResponseRedirect ( reverse ( ' work ' , kwargs = { ' work_id ' : form . cleaned_data [ ' work ' ] . id } ) )
2011-11-16 05:22:22 +00:00
else :
2012-10-07 14:58:59 +00:00
try :
work = models . Work . objects . get ( id = data [ ' claim-work ' ] )
except models . Work . DoesNotExist :
try :
work = models . WasWork . objects . get ( was = data [ ' claim-work ' ] ) . work
except models . WasWork . DoesNotExist :
raise Http404
2012-03-23 01:24:12 +00:00
rights_holder = models . RightsHolder . objects . get ( id = data [ ' claim-rights_holder ' ] )
2012-04-05 20:55:10 +00:00
active_claims = work . claim . exclude ( status = ' release ' )
context = { ' form ' : form , ' work ' : work , ' rights_holder ' : rights_holder , ' active_claims ' : active_claims }
2011-11-16 05:22:22 +00:00
return render ( request , " claim.html " , context )
2012-10-07 14:58:59 +00:00
2011-11-16 05:22:22 +00:00
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 :
2012-04-07 18:12:54 +00:00
if claim . status == ' active ' :
claim . campaigns = claim . work . campaigns . all ( )
else :
claim . campaigns = [ ]
2011-11-20 02:12:18 +00:00
for campaign in claim . campaigns :
2011-11-22 05:28:06 +00:00
if campaign . status in [ ' ACTIVE ' , ' INITIALIZED ' ] :
2012-04-03 19:50:02 +00:00
if request . method == ' POST ' and request . POST . has_key ( ' edit_managers_ %s ' % campaign . id ) :
campaign . edit_managers_form = EditManagersForm ( instance = campaign , data = request . POST , prefix = campaign . id )
if campaign . edit_managers_form . is_valid ( ) :
campaign . edit_managers_form . save ( )
2012-04-07 18:12:54 +00:00
campaign . edit_managers_form = EditManagersForm ( instance = campaign , prefix = campaign . id )
2012-04-03 19:50:02 +00:00
else :
campaign . edit_managers_form = EditManagersForm ( instance = campaign , prefix = campaign . id )
2012-09-28 21:44:08 +00:00
if claim . can_open_new :
2012-04-05 21:53:00 +00:00
if request . method == ' POST ' and request . POST . has_key ( ' work ' ) and int ( request . POST [ ' work ' ] ) == claim . work . id :
2011-11-20 02:12:18 +00:00
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 )
2013-08-09 02:32:12 +00:00
if new_campaign . type == models . BUY2UNGLUE :
new_campaign . deadline = date_today ( ) + settings . B2U_TERM
new_campaign . target = D ( settings . UNGLUEIT_MAXIMUM_TARGET )
2013-08-19 20:01:32 +00:00
new_campaign . set_cc_date_initial ( )
2013-08-09 02:32:12 +00:00
else :
new_campaign . deadline = date_today ( ) + timedelta ( days = int ( settings . UNGLUEIT_LONGEST_DEADLINE ) )
new_campaign . target = D ( settings . UNGLUEIT_MINIMUM_TARGET )
2011-11-29 04:37:17 +00:00
new_campaign . save ( )
claim . campaign_form . save_m2m ( )
2011-11-20 02:12:18 +00:00
else :
2013-08-09 02:32:12 +00:00
c_type = 2 if claim . rights_holder . can_sell else 1
claim . campaign_form = OpenCampaignForm (
data = { ' work ' : claim . work , ' name ' : claim . work . title , ' userid ' : request . user . id , ' managers_1 ' : request . user . id , ' type ' : c_type }
)
2012-09-21 16:10:13 +00:00
campaigns = request . user . campaigns . all ( )
new_campaign = None
for campaign in campaigns :
if campaign . clonable ( ) :
if request . method == ' POST ' and request . POST . has_key ( ' c %s -campaign_id ' % campaign . id ) :
clone_form = CloneCampaignForm ( data = request . POST , prefix = ' c %s ' % campaign . id )
if clone_form . is_valid ( ) :
2012-09-21 17:54:59 +00:00
campaign . clone ( )
2012-09-21 16:10:13 +00:00
else :
campaign . clone_form = CloneCampaignForm ( initial = { ' campaign_id ' : campaign . id } , prefix = ' c %s ' % campaign . id )
return render ( request , " rh_tools.html " , { ' claims ' : claims , ' campaigns ' : campaigns } )
2011-11-20 02:12:18 +00:00
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 ( )
2012-04-07 19:31:11 +00:00
form = RightsHolderForm ( )
2011-11-17 19:35:29 +00:00
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-04-25 17:55:30 +00:00
campaigns_with_active_transactions = models . Campaign . objects . filter ( transaction__status = TRANSACTION_STATUS_ACTIVE )
2011-12-21 22:32:08 +00:00
# pull out Campaigns with Transactions that are INCOMPLETE
2012-04-25 17:55:30 +00:00
campaigns_with_incomplete_transactions = models . Campaign . objects . filter ( transaction__status = TRANSACTION_STATUS_INCOMPLETE )
2011-12-21 22:32:08 +00:00
# show all Campaigns with Transactions that are COMPLETED
2012-05-04 14:30:05 +00:00
campaigns_with_completed_transactions = models . Campaign . objects . filter ( transaction__status = TRANSACTION_STATUS_COMPLETE )
2011-12-21 22:32:08 +00:00
# show Campaigns with Transactions that are CANCELED
2012-04-25 20:10:53 +00:00
campaigns_with_canceled_transactions = models . Campaign . objects . filter ( transaction__status = TRANSACTION_STATUS_CANCELED )
2011-12-21 22:32:08 +00:00
2012-04-25 20:10:53 +00:00
return ( campaigns_with_active_transactions , campaigns_with_incomplete_transactions , campaigns_with_completed_transactions , campaigns_with_canceled_transactions )
2011-12-21 22:32:08 +00:00
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 = [ ]
2012-12-31 18:46:23 +00:00
works_on_wishlist = wishlist . works . all ( )
2012-02-22 03:00:23 +00:00
2012-12-31 18:46:23 +00:00
if ( works_on_wishlist ) :
2012-03-07 18:23:34 +00:00
# querysets for tabs
2012-12-31 18:46:23 +00:00
# unglued tab is anything with an existing ebook or successful campaign
2012-03-07 18:23:34 +00:00
## .order_by() may clash with .distinct() and this should be fixed
2012-12-31 18:46:23 +00:00
unglueit_works = works_on_wishlist . filter ( campaigns__status = " SUCCESSFUL " ) . distinct ( )
works_otherwise_available = works_on_wishlist . filter ( editions__ebooks__isnull = False ) . distinct ( )
works_unglued = unglueit_works | works_otherwise_available
works_unglued = works_unglued . order_by ( ' -campaigns__status ' , ' campaigns__deadline ' , ' -num_wishes ' )
works_active = works_on_wishlist . filter ( campaigns__status = ' ACTIVE ' ) . order_by ( ' campaigns__deadline ' ) . distinct ( )
2012-03-07 18:23:34 +00:00
# everything else goes in tab 3
2012-12-31 18:46:23 +00:00
works_wished = works_on_wishlist . exclude ( pk__in = works_active . values_list ( ' pk ' , flat = True ) ) . exclude ( pk__in = works_unglued . values_list ( ' pk ' , flat = True ) ) . order_by ( ' -num_wishes ' )
2012-03-07 18:23:34 +00:00
# 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-03-28 13:08:05 +00:00
2012-05-11 18:13:09 +00:00
# default to showing the Active tab if there are active campaigns, else show Wishlist
2012-03-28 13:08:05 +00:00
if backing > 0 :
2012-05-11 18:13:09 +00:00
activetab = " #2 "
2012-12-31 20:20:03 +00:00
elif wished == 0 :
activetab = " #1 "
2012-03-28 13:08:05 +00:00
else :
2012-05-11 18:13:09 +00:00
activetab = " #3 "
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
2013-03-18 18:56:27 +00:00
if profile_obj . avatar_source == models . FACEBOOK :
profile_obj . avatar_source = models . GRAVATAR
2011-11-14 18:23:14 +00:00
if profile_form . cleaned_data [ ' clear_twitter ' ] :
profile_obj . twitter_id = " "
2013-03-18 18:56:27 +00:00
if profile_obj . avatar_source == models . TWITTER :
profile_obj . avatar_source = models . GRAVATAR
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
2013-06-10 13:29:18 +00:00
process_kindle_email ( request )
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 ,
2011-10-14 14:18:38 +00:00
" backed " : backed ,
" backing " : backing ,
" wished " : wished ,
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-28 13:08:05 +00:00
" activetab " : activetab
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 ) :
if not request . user . is_authenticated ( ) :
2013-03-08 02:48:56 +00:00
return HttpResponseRedirect ( reverse ( ' superlogin ' ) )
2012-04-25 02:20:10 +00:00
form = UserData ( )
2011-10-03 16:36:04 +00:00
if request . method == ' POST ' :
2012-04-25 02:20:10 +00:00
if ' change_username ' in request . POST . keys ( ) :
2012-05-26 21:30:12 +00:00
form = UserData ( request . POST )
form . oldusername = request . user . username
2012-04-25 02:20:10 +00:00
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
2013-03-13 01:58:15 +00:00
return render ( request , ' registration/user_change_form.html ' , { ' form ' : form } )
2011-10-03 16:36:04 +00:00
2012-10-15 03:41:17 +00:00
class ManageAccount ( FormView ) :
2012-10-14 19:31:18 +00:00
template_name = " manage_account.html "
2012-10-15 03:41:17 +00:00
form_class = PlainCCForm
def get_context_data ( self , * * kwargs ) :
context = super ( ManageAccount , self ) . get_context_data ( * * kwargs )
context [ ' STRIPE_PK ' ] = stripelib . STRIPE_PK
return context
2012-10-14 19:31:18 +00:00
2012-10-15 03:41:17 +00:00
def form_valid ( self , form ) :
""" save the token, make an account """
p = PaymentManager ( )
stripe_token = form . cleaned_data [ " stripe_token " ]
# if we get a stripe_token, create a new stripe account for the user
if stripe_token :
try :
p . make_account ( user = self . request . user , host = settings . PAYMENT_PROCESSOR , token = stripe_token )
except baseprocessor . ProcessorError as e :
2012-10-15 04:42:09 +00:00
return render ( self . request , " pledge_card_error.html " , { ' exception ' : e } )
2012-10-15 04:16:56 +00:00
next = self . request . REQUEST . get ( ' next ' , None )
if next :
return HttpResponseRedirect ( next )
else :
return render ( self . request , self . template_name , self . get_context_data ( ) )
2012-10-15 03:41:17 +00:00
2011-09-29 01:36:47 +00:00
def search ( request ) :
2013-03-30 01:11:01 +00:00
q = request . GET . get ( ' q ' , ' ' )
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 )
2013-03-01 17:07:15 +00:00
2013-03-30 01:11:01 +00:00
if q != ' ' and page == 1 :
2013-03-01 17:07:15 +00:00
work_query = Q ( title__icontains = q ) | Q ( editions__authors__name__icontains = q ) | Q ( subjects__name__iexact = q )
campaign_works = models . Work . objects . exclude ( campaigns = None ) . filter ( work_query ) . distinct ( )
else :
2013-03-19 20:43:23 +00:00
campaign_works = None
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 ,
2013-03-01 17:07:15 +00:00
" ungluers " : ungluers ,
" campaign_works " : campaign_works
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-10-16 15:36:51 +00:00
request . user . wishlist . add_work ( edition . work , ' user ' , notify = True )
2013-02-26 20:30:14 +00:00
return HttpResponse ( ' added googlebooks id ' )
2012-01-31 19:54:48 +00:00
except bookloader . LookupFailure :
logger . warning ( " failed to load googlebooks_id %s " % googlebooks_id )
2013-06-05 15:06:07 +00:00
return HttpResponse ( ' error adding googlebooks id ' )
2012-01-31 19:54:48 +00:00
except Exception , e :
logger . warning ( " Error in wishlist adding %s " % ( e ) )
2013-02-26 20:30:14 +00:00
return HttpResponse ( ' error adding googlebooks id ' )
2011-09-29 11:44:03 +00:00
# TODO: redirect to work page, when it exists
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 )
2013-02-26 20:30:14 +00:00
return HttpResponse ( ' removed work from wishlist ' )
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
2012-10-16 15:36:51 +00:00
request . user . wishlist . add_work ( work , ' user ' , notify = True )
2013-02-26 20:30:14 +00:00
return HttpResponse ( ' added work to wishlist ' )
2011-10-14 02:16:28 +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-12-06 16:42:02 +00:00
2012-12-10 21:01:50 +00:00
transactions = Transaction . objects . filter ( status__in = [ TRANSACTION_STATUS_ACTIVE , TRANSACTION_STATUS_COMPLETE ] )
2012-12-06 16:42:02 +00:00
transactions . sum = transactions . aggregate ( Sum ( ' amount ' ) ) [ ' amount__sum ' ]
transactions . today = transactions . filter ( date_created__range = ( date_today ( ) , now ( ) ) )
transactions . today . sum = transactions . today . aggregate ( Sum ( ' amount ' ) ) [ ' amount__sum ' ]
transactions . days7 = transactions . filter ( date_created__range = ( date_today ( ) - timedelta ( days = 7 ) , now ( ) ) )
transactions . days7 . sum = transactions . days7 . aggregate ( Sum ( ' amount ' ) ) [ ' amount__sum ' ]
transactions . year = transactions . filter ( date_created__year = date_today ( ) . year )
transactions . year . sum = transactions . year . aggregate ( Sum ( ' amount ' ) ) [ ' amount__sum ' ]
transactions . month = transactions . filter ( date_created__month = date_today ( ) . month )
transactions . month . sum = transactions . month . aggregate ( Sum ( ' amount ' ) ) [ ' amount__sum ' ]
transactions . yesterday = transactions . filter ( date_created__range = ( date_today ( ) - timedelta ( days = 1 ) , date_today ( ) ) )
transactions . yesterday . sum = transactions . yesterday . aggregate ( Sum ( ' amount ' ) ) [ ' amount__sum ' ]
2012-03-08 03:06:30 +00:00
return {
' users ' : users ,
' works ' : works ,
' ebooks ' : ebooks ,
' wishlists ' : wishlists ,
2012-12-11 15:53:12 +00:00
' transactions ' : transactions ,
2012-03-08 03:06:30 +00:00
}
2012-07-20 18:29:04 +00:00
class InfoLangView ( TemplateView ) :
def get_template_names ( self , * * kwargs ) :
if self . kwargs [ ' template_name ' ] :
return ( self . kwargs [ ' template_name ' ] )
else :
return ( ' languages.html ' )
def get_context_data ( self , * * kwargs ) :
languages = models . Work . objects . filter ( num_wishes__gte = 1 ) . values ( ' language ' ) . annotate ( lang_count = Count ( ' language ' ) ) . order_by ( ' -lang_count ' )
return {
' wished_languages ' : languages ,
}
2012-03-08 03:06:30 +00:00
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 )
2013-02-26 17:43:54 +00:00
@require_POST
@login_required
def msg ( request ) :
form = MsgForm ( data = request . POST )
if form . is_valid ( ) :
if not request . user . is_staff and request . user not in form . cleaned_data [ ' work ' ] . last_campaign ( ) . managers . all ( ) :
2013-03-05 04:35:43 +00:00
logger . warning ( " unauthorized attempt to send message by %s for %s " % ( request . user , form . cleaned_data [ ' work ' ] ) )
2013-02-26 17:43:54 +00:00
raise Http404
2013-03-05 04:11:50 +00:00
supporter_message . send ( sender = request . user , msg = form . cleaned_data [ " msg " ] , work = form . cleaned_data [ " work " ] , supporter = form . cleaned_data [ " supporter " ] )
2013-02-26 17:43:54 +00:00
return HttpResponse ( " message sent " )
else :
2013-03-05 04:35:43 +00:00
logger . info ( " Invalid form for user %s " , request . user )
2013-02-26 17:43:54 +00:00
raise Http404
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
2012-05-14 02:59:07 +00:00
def emailshare ( request , action ) :
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 ' ]
2012-05-13 20:38:58 +00:00
sender = ' %s via Unglue.it < %s > ' % ( request . user . username , request . user . email )
2011-12-31 18:49:23 +00:00
recipient = form . cleaned_data [ ' recipient ' ]
2012-04-25 02:20:10 +00:00
send_mail_task . delay ( subject , message , sender , [ recipient ] )
2011-12-31 18:49:23 +00:00
try :
next = form . cleaned_data [ ' next ' ]
except :
2013-01-21 17:00:01 +00:00
# if we totally failed to have a next value, we should still redirect somewhere useful
2013-03-09 18:29:03 +00:00
next = ' https://unglue.it '
2011-12-31 18:49:23 +00:00
return HttpResponseRedirect ( next )
2013-01-21 17:00:01 +00:00
else :
work = None
status = None
2012-05-12 15:12:27 +00:00
2011-12-31 18:49:23 +00:00
try :
next = request . GET [ ' next ' ]
2012-05-14 02:59:07 +00:00
work_id = next . split ( ' / ' ) [ - 2 ]
work_id = int ( work_id )
work = models . Work . objects . get ( pk = work_id )
if action == ' pledge ' :
2012-05-12 15:12:27 +00:00
message = render_to_string ( ' emails/i_just_pledged.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
subject = " Help me unglue " + work . title
2012-03-12 17:18:11 +00:00
else :
2012-04-25 02:17:30 +00:00
try :
2012-05-12 15:12:27 +00:00
status = work . last_campaign ( ) . status
2012-04-25 02:17:30 +00:00
except :
status = None
2012-03-26 19:26:47 +00:00
2012-04-25 02:17:30 +00:00
# customize the call to action depending on campaign status
2013-01-16 16:23:28 +00:00
if status == ' SUCCESSFUL ' or work . first_ebook ( ) :
message = render_to_string ( ' emails/read_this.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
subject = ' I think you \' d like this book I \' m reading '
elif status == ' ACTIVE ' :
2012-05-12 15:12:27 +00:00
message = render_to_string ( ' emails/pledge_this.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
2013-01-16 16:23:28 +00:00
subject = ' Please help me give this book to the world '
2012-04-25 02:17:30 +00:00
else :
2012-05-12 15:12:27 +00:00
message = render_to_string ( ' emails/wish_this.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
2013-01-16 16:23:28 +00:00
subject = ' Come see one of my favorite books on Unglue.it '
2012-04-25 17:45:18 +00:00
2012-05-12 15:12:27 +00:00
form = EmailShareForm ( initial = { ' next ' : next , ' subject ' : subject , ' message ' : message } )
2011-12-31 18:49:23 +00:00
except :
2013-01-21 17:00:01 +00:00
pass
if action == ' pledge ' :
message = render_to_string ( ' emails/i_just_pledged.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
subject = " Help me unglue " + work . title
else :
# customize the call to action depending on campaign status
if status == ' ACTIVE ' :
message = render_to_string ( ' emails/pledge_this.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
subject = ' Please help me give this book to the world '
elif work :
message = render_to_string ( ' emails/wish_this.txt ' , { ' request ' : request , ' work ' : work , ' site ' : Site . objects . get_current ( ) } )
subject = ' Come see one of my favorite books on Unglue.it '
else :
# for email shares not bound to a campaign or pledge
message = render_to_string ( ' emails/join_me.txt ' , { ' request ' : request , ' site ' : Site . objects . get_current ( ) } )
subject = " Help me give books to the world "
form = EmailShareForm ( initial = { ' next ' : next , ' subject ' : subject , ' message ' : message } )
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
2013-03-27 16:22:30 +00:00
def ask_rh ( request , campaign_id ) :
campaign = get_object_or_404 ( models . Campaign , id = campaign_id )
return feedback ( request , recipient = campaign . email , template = " ask_rh.html " ,
message_template = " ask_rh.txt " ,
redirect_url = reverse ( ' work ' , args = [ campaign . work . id ] ) ,
extra_context = { ' campaign ' : campaign , ' subject ' : campaign } )
def feedback ( request , recipient = ' support@gluejar.com ' , template = ' feedback.html ' , message_template = ' feedback.txt ' , extra_context = None , redirect_url = None ) :
context = extra_context or { }
context [ ' num1 ' ] = randint ( 0 , 10 )
context [ ' num2 ' ] = randint ( 0 , 10 )
context [ ' answer ' ] = context [ ' num1 ' ] + context [ ' 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 ( ) :
2013-03-27 16:22:30 +00:00
context . update ( form . cleaned_data )
context [ ' request ' ] = request
if extra_context :
context . update ( extra_context )
message = render_to_string ( message_template , context )
send_mail_task . delay ( context [ ' subject ' ] , message , context [ ' sender ' ] , [ recipient ] )
if redirect_url :
return HttpResponseRedirect ( redirect_url )
2012-01-16 00:02:50 +00:00
else :
2013-03-27 16:22:30 +00:00
return render ( request , " thanks.html " , context )
2012-01-09 20:53:09 +00:00
else :
2013-03-27 16:22:30 +00:00
context [ ' num1 ' ] = request . POST [ ' num1 ' ]
context [ ' 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 ( ) :
2013-03-27 16:22:30 +00:00
context [ ' sender ' ] = request . user . email ;
2012-01-31 15:07:52 +00:00
try :
2013-03-27 16:22:30 +00:00
context [ ' page ' ] = request . GET [ ' page ' ]
2012-01-31 15:07:52 +00:00
except :
2013-03-27 16:22:30 +00:00
context [ ' page ' ] = ' / '
if not context . has_key ( ' subject ' ) :
context [ ' subject ' ] = " Feedback on page " + context [ ' page ' ]
form = FeedbackForm ( initial = context )
context [ ' form ' ] = form
return render ( request , template , context )
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 } )
2012-04-04 16:15:18 +00:00
def campaign_archive_js ( request ) :
""" proxy for mailchimp js """
response = HttpResponse ( )
r = requests . get ( settings . CAMPAIGN_ARCHIVE_JS )
response . status_code = r . status_code
response . content = r . content
response [ " Content-Type " ] = " text/javascript "
return response
2012-08-15 13:40:37 +00:00
def lockss ( request , work_id ) :
2012-08-29 19:56:14 +00:00
"""
2012-09-18 18:16:06 +00:00
manifest pages for lockss harvester - - individual works
2012-08-29 19:56:14 +00:00
"""
2012-08-24 19:14:32 +00:00
work = safe_get_work ( work_id )
2012-08-27 20:48:07 +00:00
try :
2012-09-12 14:11:49 +00:00
ebooks = work . ebooks ( ) . filter ( edition__unglued = True )
2012-08-27 20:48:07 +00:00
except :
2012-09-12 14:11:49 +00:00
ebooks = None
2012-08-15 13:40:37 +00:00
authors = list ( models . Author . objects . filter ( editions__work = work ) . all ( ) )
2012-09-12 14:11:49 +00:00
return render ( request , " lockss.html " , { ' work ' : work , ' ebooks ' : ebooks , ' authors ' : authors } )
2012-08-24 19:14:32 +00:00
2012-09-18 18:16:06 +00:00
def lockss_manifest ( request , year ) :
"""
manifest pages for lockss harvester - - yearly indices
( lockss needs pages listing all books unglued by year , with
programmatically determinable URLs )
"""
year = int ( year )
start_date = date ( year , 1 , 1 )
end_date = date ( year , 12 , 31 )
try :
ebooks = models . Edition . objects . filter ( unglued = True ) . filter ( created__range = ( start_date , end_date ) )
except :
ebooks = None
return render ( request , " lockss_manifest.html " , { ' ebooks ' : ebooks , ' year ' : year } )
2013-06-27 17:10:33 +00:00
2012-08-24 19:14:32 +00:00
def download ( request , work_id ) :
context = { }
work = safe_get_work ( work_id )
2013-01-16 17:50:20 +00:00
site = Site . objects . get_current ( )
context . update ( { ' work ' : work , ' site ' : site } )
2012-08-24 19:14:32 +00:00
2012-09-10 19:18:40 +00:00
unglued_ebooks = work . ebooks ( ) . filter ( edition__unglued = True )
other_ebooks = work . ebooks ( ) . filter ( edition__unglued = False )
2013-06-12 19:11:43 +00:00
formats = { }
2013-06-12 19:24:26 +00:00
2013-06-25 05:35:09 +00:00
for ebook in work . ebooks ( ) . all ( ) :
formats [ ebook . format ] = ebook
2013-06-12 19:24:26 +00:00
2013-07-05 13:05:26 +00:00
# google ebooks have a captcha which breaks some of our services
non_google_ebooks = work . ebooks ( ) . exclude ( provider = ' Google Books ' )
2012-09-26 18:59:13 +00:00
try :
2013-07-05 13:05:26 +00:00
kindle_ebook_id = non_google_ebooks . filter ( format = ' mobi ' ) [ 0 ] . id
except IndexError :
try :
kindle_ebook_id = non_google_ebooks . filter ( format = ' pdf ' ) [ 0 ] . id
except IndexError :
kindle_ebook_id = None
2013-06-12 19:24:26 +00:00
2012-09-26 18:59:13 +00:00
try :
2013-07-05 13:05:26 +00:00
readmill_epub_ebook = non_google_ebooks . filter ( format = ' epub ' ) [ 0 ]
2013-06-20 18:34:44 +00:00
#readmill_epub_url = settings.BASE_URL_SECURE + reverse('download_ebook',args=[readmill_epub_ebook.id])
readmill_epub_url = readmill_epub_ebook . url
2012-09-26 18:59:13 +00:00
except :
readmill_epub_url = None
2013-06-26 18:36:04 +00:00
agent = request . META . get ( ' HTTP_USER_AGENT ' , ' ' )
2013-06-10 16:58:19 +00:00
iOS = ' iPad ' in agent or ' iPhone ' in agent or ' iPod ' in agent
2013-06-12 19:11:43 +00:00
iOS_app = iOS and not ' Safari ' in agent
android = ' Android ' in agent
desktop = not iOS and not android
2012-08-24 19:14:32 +00:00
context . update ( {
2012-09-10 19:18:40 +00:00
' unglued_ebooks ' : unglued_ebooks ,
2012-09-19 14:25:23 +00:00
' other_ebooks ' : other_ebooks ,
2013-06-12 19:11:43 +00:00
' formats ' : formats ,
2013-05-31 21:15:22 +00:00
' kindle_ebook_id ' : kindle_ebook_id ,
2012-09-26 18:59:13 +00:00
' readmill_epub_url ' : readmill_epub_url ,
2013-06-10 16:58:19 +00:00
' base_url ' : settings . BASE_URL_SECURE ,
' iOS ' : iOS ,
2013-06-12 19:11:43 +00:00
' iOS_app ' : iOS_app ,
' android ' : android ,
' desktop ' : desktop
2012-08-24 19:14:32 +00:00
} )
2013-06-07 15:22:54 +00:00
2012-08-24 19:14:32 +00:00
return render ( request , " download.html " , context )
2012-08-27 19:35:29 +00:00
2013-06-27 17:10:33 +00:00
def download_purchased ( request , work_id ) :
if request . user . is_anonymous :
HttpResponseRedirect ( ' /accounts/login/download/ ' )
return download ( request , work_id )
2012-08-27 19:35:29 +00:00
def about ( request , facet ) :
template = " about_ " + facet + " .html "
2013-05-03 18:48:36 +00:00
try :
return render ( request , template )
except TemplateDoesNotExist :
return render ( request , " about.html " )
2012-09-07 20:08:03 +00:00
2013-03-04 22:01:33 +00:00
@login_required
@csrf_exempt
def ml_status ( request ) :
return render ( request , " ml_status.html " )
@require_POST
@login_required
def ml_subscribe ( request ) :
request . user . profile . ml_subscribe ( double_optin = False , send_welcome = True , merge_vars = { " OPTIN_IP " : request . META [ ' REMOTE_ADDR ' ] , " OPTIN_TIME " : now ( ) . isoformat ( ) } )
return HttpResponseRedirect ( reverse ( " notification_notice_settings " ) )
@require_POST
@login_required
def ml_unsubscribe ( request ) :
request . user . profile . ml_unsubscribe ( )
return HttpResponseRedirect ( reverse ( " notification_notice_settings " ) )
2013-04-04 14:15:29 +00:00
2013-04-08 18:16:08 +00:00
def press ( request ) :
2013-04-04 14:15:29 +00:00
latest_items = models . Press . objects . order_by ( ' -date ' ) [ : 3 ]
2013-04-04 15:40:44 +00:00
highlighted_items = models . Press . objects . filter ( highlight = True ) . order_by ( ' -date ' )
all_items = models . Press . objects . exclude ( highlight = True ) . order_by ( ' -date ' )
2013-04-04 14:15:29 +00:00
return render ( request , " press_new.html " , {
' latest_items ' : latest_items ,
' highlighted_items ' : highlighted_items ,
' all_items ' : all_items
} )
2013-04-04 15:09:18 +00:00
def press_submitterator ( request ) :
if not request . user . is_staff :
return render ( request , " admins_only.html " )
else :
2013-04-08 18:16:08 +00:00
title = ' '
2013-04-04 15:09:18 +00:00
if request . method == ' POST ' :
form = PressForm ( request . POST )
if form . is_valid ( ) :
form . save ( )
2013-04-08 18:16:08 +00:00
title = form . cleaned_data [ ' title ' ]
2013-04-04 15:09:18 +00:00
else :
form = PressForm ( )
return render ( request , ' press_submitterator.html ' , {
' form ' : form ,
2013-04-08 18:16:08 +00:00
' title ' : title
2013-04-04 15:09:18 +00:00
} )
2013-05-31 15:34:51 +00:00
2013-05-31 19:19:58 +00:00
@login_required
2013-06-24 17:53:28 +00:00
def kindle_config ( request , kindle_ebook_id = None ) :
def get_title_from_kindle_id ( kindle_ebook_id ) :
# protect against user URL manipulation
2013-06-25 20:01:08 +00:00
work = None
2013-06-24 17:53:28 +00:00
if kindle_ebook_id :
try :
ebook = models . Ebook . objects . get ( pk = kindle_ebook_id )
2013-06-25 20:01:08 +00:00
work = ebook . edition . work
2013-06-24 17:53:28 +00:00
except :
kindle_ebook_id = None
2013-06-25 20:01:08 +00:00
return work , kindle_ebook_id
2013-06-24 17:53:28 +00:00
2013-06-25 20:01:08 +00:00
( work , kindle_ebook_id ) = get_title_from_kindle_id ( kindle_ebook_id )
template = " kindle_config.html "
2013-05-31 19:19:58 +00:00
if request . method == ' POST ' :
form = KindleEmailForm ( request . POST )
if form . is_valid ( ) :
request . user . profile . kindle_email = form . cleaned_data [ ' kindle_email ' ]
request . user . profile . save ( )
2013-06-25 20:01:08 +00:00
template = " kindle_change_successful.html "
2013-05-31 19:19:58 +00:00
else :
2013-06-24 17:53:28 +00:00
form = KindleEmailForm ( )
return render (
request ,
2013-06-25 20:01:08 +00:00
template ,
{ ' form ' : form , ' kindle_ebook_id ' : kindle_ebook_id , ' work ' : work }
2013-06-24 17:53:28 +00:00
)
2013-06-05 15:06:07 +00:00
2013-05-31 21:15:22 +00:00
@require_POST
@csrf_exempt
2013-06-05 15:06:07 +00:00
def send_to_kindle ( request , kindle_ebook_id , javascript = ' 0 ' ) :
2013-06-25 05:11:43 +00:00
# make sure to gracefully communicate with both js and non-js (kindle!) users
2013-06-05 15:06:07 +00:00
def local_response ( request , javascript , message ) :
if javascript == ' 1 ' :
2013-06-25 05:11:43 +00:00
return render ( request , ' kindle_response_message.html ' , { ' message ' : message } )
2013-06-05 15:06:07 +00:00
else :
# can't pass context with HttpResponseRedirect
# must use an HttpResponse, not a render(), after POST
return HttpResponseRedirect ( reverse ( ' send_to_kindle_graceful ' , args = ( message , ) ) )
2013-06-10 15:57:59 +00:00
ebook = models . Ebook . objects . get ( pk = kindle_ebook_id )
if request . POST . has_key ( ' kindle_email ' ) :
kindle_email = request . POST [ ' kindle_email ' ]
try :
validate_email ( kindle_email )
except ValidationError :
return local_response ( request , javascript , 3 )
request . session [ ' kindle_email ' ] = kindle_email
2013-06-24 17:53:28 +00:00
elif request . user . is_authenticated ( ) :
2013-06-10 15:57:59 +00:00
kindle_email = request . user . profile . kindle_email
2013-06-05 15:06:07 +00:00
2013-05-31 21:15:22 +00:00
# don't forget to increment the download counter!
2013-06-03 15:17:25 +00:00
assert ebook . format == ' mobi ' or ebook . format == ' pdf '
2013-05-31 21:15:22 +00:00
ebook . increment ( )
2013-06-05 15:06:07 +00:00
logger . info ( ' ebook: {0} , user_ip: {1} ' . format ( kindle_ebook_id , request . META [ ' REMOTE_ADDR ' ] ) )
2013-05-31 21:15:22 +00:00
2013-06-03 15:17:25 +00:00
title = ebook . edition . title
title = title . replace ( ' ' , ' _ ' )
2013-07-05 12:43:02 +00:00
"""
TO FIX rigorously :
Amazon SES has a 10 MB size limit ( http : / / aws . amazon . com / ses / faqs / #49) in messages sent
to determine whether the file will meet this limit , we probably need to compare the
size of the mime - encoded file to 10 MB . ( and it ' s unclear exactly what the Amazon FAQ means precisely by
MB either : http : / / en . wikipedia . org / wiki / Megabyte ) http : / / www . velocityreviews . com / forums / t335208 - how - to - get - size - of - email - attachment . html might help
for the moment , we will hardwire a 749229 limit in filesize :
* assume conservative size of megabyte , 1000000 B
* leave 1 KB for headers
* mime encoding will add 33 % to filesize
This won ' t perfectly measure size of email, but should be safe, and is much faster than doing the check after download.
"""
2013-06-03 15:17:25 +00:00
filehandle = urllib . urlopen ( ebook . url )
2013-06-04 14:22:11 +00:00
filesize = int ( filehandle . info ( ) . getheaders ( " Content-Length " ) [ 0 ] )
2013-07-05 12:43:02 +00:00
if filesize > 7492232 :
2013-06-05 15:06:07 +00:00
logger . info ( ' ebook %s is too large to be emailed ' % kindle_ebook_id )
return local_response ( request , javascript , 0 )
2013-06-07 14:19:06 +00:00
2013-06-03 21:18:42 +00:00
try :
2013-06-24 19:42:51 +00:00
email = EmailMessage ( from_email = ' notices@gluejar.com ' ,
2013-06-07 14:19:06 +00:00
to = [ kindle_email ] )
2013-06-03 21:18:42 +00:00
email . attach ( title + ' . ' + ebook . format , filehandle . read ( ) )
email . send ( )
2013-06-04 14:22:11 +00:00
except :
2013-06-10 15:12:54 +00:00
logger . warning ( ' Unexpected error: %s ' , sys . exc_info ( ) )
2013-06-05 15:06:07 +00:00
return local_response ( request , javascript , 1 )
2013-06-10 15:57:59 +00:00
if request . POST . has_key ( ' kindle_email ' ) and not request . user . is_authenticated ( ) :
2013-06-10 13:29:18 +00:00
return HttpResponseRedirect ( reverse ( ' superlogin ' ) )
2013-06-05 15:06:07 +00:00
return local_response ( request , javascript , 2 )
2013-06-10 13:29:18 +00:00
2013-06-05 15:06:07 +00:00
def send_to_kindle_graceful ( request , message ) :
return render (
request ,
' kindle_response_graceful_degradation.html ' ,
2013-06-25 05:11:43 +00:00
{ ' message ' : int ( message ) }
2013-06-10 15:59:19 +00:00
)
2013-07-08 15:14:09 +00:00
2013-07-29 21:59:52 +00:00
def marc ( request , userlist = None ) :
2013-07-26 22:30:45 +00:00
link_target = ' UNGLUE '
libpref = { ' marc_link_target ' : settings . MARC_CHOICES [ 1 ] }
2013-07-24 18:52:01 +00:00
try :
2013-07-26 22:30:45 +00:00
libpref = request . user . libpref
link_target = libpref . marc_link_target
except :
if not request . user . is_anonymous ( ) :
libpref = models . Libpref ( user = request . user )
2013-07-29 21:59:52 +00:00
if userlist :
records = [ ]
user = get_object_or_404 ( User , username = userlist )
for work in user . wishlist . works . all ( ) :
records . extend ( models . MARCRecord . objects . filter ( edition__work = work , link_target = link_target ) )
else :
records = models . MARCRecord . objects . filter ( link_target = link_target )
2013-07-08 15:14:09 +00:00
return render (
request ,
' marc.html ' ,
2013-07-29 21:59:52 +00:00
{ ' records ' : records , ' libpref ' : libpref , ' userlist ' : userlist }
2013-07-08 15:14:09 +00:00
)
2013-07-15 20:35:41 +00:00
class MARCUngluifyView ( FormView ) :
template_name = ' marcungluify.html '
form_class = MARCUngluifyForm
success_url = reverse_lazy ( ' MARCUngluify ' )
2013-07-29 20:35:50 +00:00
# allow a get param to specify the edition
def get_initial ( self ) :
if self . request . method == ' GET ' :
edition = self . request . GET . get ( ' edition ' , None )
if models . Edition . objects . filter ( id = edition ) . count ( ) :
edition = models . Edition . objects . filter ( id = edition ) [ 0 ]
if edition . ebooks . count ( ) :
return { ' edition ' : edition . id }
return { }
2013-07-15 20:35:41 +00:00
def form_valid ( self , form ) :
2013-07-18 19:49:54 +00:00
edition = form . cleaned_data [ ' edition ' ]
2013-07-17 17:03:35 +00:00
2013-07-19 16:47:36 +00:00
try :
ungluify_record . makemarc (
marcfile = self . request . FILES [ ' file ' ] ,
edition = edition
)
messages . success (
self . request ,
" You have successfully added a MARC record. Hooray! Add another? "
)
except SAXParseException :
messages . error (
self . request ,
" Sorry, couldn ' t parse that file. "
)
2013-07-23 16:23:04 +00:00
return super ( MARCUngluifyView , self ) . form_valid ( form )
class MARCConfigView ( FormView ) :
template_name = ' marc_config.html '
form_class = MARCFormatForm
success_url = reverse_lazy ( ' marc ' )
def form_valid ( self , form ) :
2013-07-25 14:18:36 +00:00
marc_link_target = form . cleaned_data [ ' marc_link_target ' ]
2013-07-26 22:30:45 +00:00
try :
libpref = self . request . user . libpref
except :
libpref = models . Libpref ( user = self . request . user )
libpref . marc_link_target = marc_link_target
libpref . save ( )
2013-07-23 16:23:04 +00:00
messages . success (
self . request ,
" Your preferences have been changed. "
)
if reverse ( ' marc_config ' , args = [ ] ) in self . request . META [ ' HTTP_REFERER ' ] :
return HttpResponseRedirect ( reverse ( ' marc_config ' , args = [ ] ) )
else :
return super ( MARCConfigView , self ) . form_valid ( form )
2013-07-24 18:52:01 +00:00
def marc_concatenate ( request ) :
"""
options for future work . . .
cache files : keep records of each combo created , check before building anew ?
dispatch as background process , email when done ?
if not caching , delete files on s3 after a while ?
make the control flow suck less during file write
2013-07-29 19:57:33 +00:00
Can be used as a GET URL
2013-07-24 18:52:01 +00:00
"""
2013-07-29 19:57:33 +00:00
if request . method == ' POST ' :
params = request . POST
elif request . method == ' GET ' :
params = request . GET
else :
return HttpResponseNotFound
format = params [ ' format ' ]
2013-07-24 18:52:01 +00:00
2013-07-29 19:57:33 +00:00
# extract the user-selected records from the params QueryDict
2013-07-24 18:52:01 +00:00
selected_records = list (
2013-07-29 19:57:33 +00:00
k for k in params if params [ k ] == u ' on '
2013-07-24 18:52:01 +00:00
)
if not selected_records :
messages . error (
request ,
" Please select at least one record to download. "
)
return HttpResponseRedirect ( reverse ( ' marc ' , args = [ ] ) )
# keep test files from stepping on production files
if ' /unglue.it ' in settings . BASE_URL :
directory = ' marc/ '
else :
directory = ' marc_test/ '
# write the concatenated file
datestamp = now ( ) . strftime ( ' % Y % m %d % H % M % S ' )
filename = directory + datestamp + ' . ' + format
with default_storage . open ( filename , ' w ' ) as outfile :
if format == ' xml ' :
string = ( ' <?xml version= " 1.0 " encoding= " UTF-8 " standalone= " yes " ?> '
' <collection '
' xmlns:xsi= " http://www.w3.org/2001/XMLSchema-instance " '
' xmlns= " http://www.loc.gov/MARC21/slim " '
' xsi:schemaLocation= " http://www.loc.gov/MARC21/slim '
' http://www.loc.gov/standards/marcxml/schema/ '
' MARC21slim.xsd " > ' )
outfile . write ( string )
for record in selected_records :
record_id = long ( record [ 7 : ] )
if format == ' xml ' :
record_url = models . MARCRecord . objects . get (
pk = record_id
) . xml_record
logger . info ( record_url )
elif format == ' mrc ' :
record_url = models . MARCRecord . objects . get (
pk = record_id
) . mrc_record
logger . info ( record_url )
try :
record_file = urllib . urlopen ( record_url ) . read ( )
outfile . write ( record_file )
except IOError :
logger . warning ( ' MARC record with id number %s has a problem with its URL ' % record_id )
if format == ' xml ' :
string = ( ' </collection> ' )
outfile . write ( string )
download_url = default_storage . url ( filename )
return HttpResponseRedirect ( download_url )
2013-07-23 16:23:04 +00:00