<s> import datetime <EOL> import random <EOL> from django . db import models <EOL> from django . core . mail import send_mail <EOL> from django . conf import settings <EOL> from django . template . loader import render_to_string <EOL> from django . utils . translation import ugettext_lazy as _ <EOL> from django . utils . hashcompat import sha_constructor <EOL> from django . contrib . auth . models import User <EOL> from django . contrib . sites . models import Site , RequestSite <EOL> import app_settings <EOL> import signals <EOL> def performance_calculator_invite_only ( invitation_stats ) : <EOL> """<STR_LIT>""" <EOL> if app_settings . INVITE_ONLY : <EOL> total = invitation_stats . available + invitation_stats . sent <EOL> try : <EOL> send_ratio = float ( invitation_stats . sent ) / total <EOL> except ZeroDivisionError : <EOL> send_ratio = <NUM_LIT:0.0> <EOL> accept_ratio = performance_calculator_invite_optional ( invitation_stats ) <EOL> return min ( ( send_ratio + accept_ratio ) * <NUM_LIT> , <NUM_LIT:1.0> ) <EOL> def performance_calculator_invite_optional ( invitation_stats ) : <EOL> try : <EOL> accept_ratio = float ( invitation_stats . accepted ) / invitation_stats . sent <EOL> return min ( accept_ratio , <NUM_LIT:1.0> ) <EOL> except ZeroDivisionError : <EOL> return <NUM_LIT:0.0> <EOL> DEFAULT_PERFORMANCE_CALCULATORS = { <EOL> True : performance_calculator_invite_only , <EOL> False : performance_calculator_invite_optional , <EOL> } <EOL> class InvitationError ( Exception ) : <EOL> pass <EOL> class InvitationManager ( models . Manager ) : <EOL> def invite ( self , user , email ) : <EOL> """<STR_LIT>""" <EOL> invitation = None <EOL> try : <EOL> invitation = self . filter ( user = user , email = email ) [ <NUM_LIT:0> ] <EOL> if not invitation . is_valid ( ) : <EOL> invitation = None <EOL> except ( Invitation . DoesNotExist , IndexError ) : <EOL> pass <EOL> if invitation is None : <EOL> user . invitation_stats . use ( ) <EOL> key = '<STR_LIT>' % ( settings . SECRET_KEY , <EOL> random . random ( ) , <EOL> user . email , <EOL> email ) <EOL> key = sha_constructor ( key ) . hexdigest ( ) <EOL> invitation = self . create ( user = user , email = email , key = key ) <EOL> return invitation <EOL> invite . alters_data = True <EOL> def find ( self , invitation_key ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> invitation = self . filter ( key = invitation_key ) [ <NUM_LIT:0> ] <EOL> except IndexError : <EOL> raise Invitation . DoesNotExist <EOL> if not invitation . is_valid ( ) : <EOL> invitation . delete ( ) <EOL> raise Invitation . DoesNotExist <EOL> return invitation <EOL> def valid ( self ) : <EOL> """<STR_LIT>""" <EOL> expiration = datetime . datetime . now ( ) - datetime . timedelta ( <EOL> app_settings . EXPIRE_DAYS ) <EOL> return self . get_query_set ( ) . filter ( date_invited__gte = expiration ) <EOL> def invalid ( self ) : <EOL> """<STR_LIT>""" <EOL> expiration = datetime . datetime . now ( ) - datetime . timedelta ( <EOL> app_settings . EXPIRE_DAYS ) <EOL> return self . get_query_set ( ) . filter ( date_invited__le = expiration ) <EOL> class Invitation ( models . Model ) : <EOL> user = models . ForeignKey ( User , related_name = '<STR_LIT>' ) <EOL> email = models . EmailField ( _ ( u'<STR_LIT>' ) ) <EOL> key = models . CharField ( _ ( u'<STR_LIT>' ) , max_length = <NUM_LIT> , unique = True ) <EOL> date_invited = models . DateTimeField ( _ ( u'<STR_LIT>' ) , <EOL> default = datetime . datetime . now ) <EOL> objects = InvitationManager ( ) <EOL> class Meta : <EOL> verbose_name = _ ( u'<STR_LIT>' ) <EOL> verbose_name_plural = _ ( u'<STR_LIT>' ) <EOL> ordering = ( '<STR_LIT>' , ) <EOL> def __unicode__ ( self ) : <EOL> return _ ( '<STR_LIT>' ) % { <EOL> '<STR_LIT:username>' : self . user . username , <EOL> '<STR_LIT:email>' : self . email , <EOL> '<STR_LIT:date>' : str ( self . date_invited . date ( ) ) , <EOL> } <EOL> @ models . permalink <EOL> def get_absolute_url ( self ) : <EOL> return ( '<STR_LIT>' , ( ) , { '<STR_LIT>' : self . key } ) <EOL> @ property <EOL> def _expires_at ( self ) : <EOL> return self . date_invited + datetime . timedelta ( app_settings . EXPIRE_DAYS ) <EOL> def is_valid ( self ) : <EOL> """<STR_LIT>""" <EOL> return datetime . datetime . now ( ) < self . _expires_at <EOL> def expiration_date ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _expires_at . date ( ) <EOL> expiration_date . short_description = _ ( u'<STR_LIT>' ) <EOL> expiration_date . admin_order_field = '<STR_LIT>' <EOL> def send_email ( self , email = None , site = None , request = None ) : <EOL> """<STR_LIT>""" <EOL> email = email or self . email <EOL> if site is None : <EOL> if Site . _meta . installed : <EOL> site = Site . objects . get_current ( ) <EOL> elif request is not None : <EOL> site = RequestSite ( request ) <EOL> subject = render_to_string ( '<STR_LIT>' , <EOL> { '<STR_LIT>' : self , '<STR_LIT>' : site } ) <EOL> subject = '<STR_LIT>' . join ( subject . splitlines ( ) ) <EOL> message = render_to_string ( '<STR_LIT>' , { <EOL> '<STR_LIT>' : self , <EOL> '<STR_LIT>' : app_settings . EXPIRE_DAYS , <EOL> '<STR_LIT>' : site <EOL> } ) <EOL> send_mail ( subject , message , settings . DEFAULT_FROM_EMAIL , [ email ] ) <EOL> signals . invitation_sent . send ( sender = self ) <EOL> def mark_accepted ( self , new_user ) : <EOL> """<STR_LIT>""" <EOL> self . user . invitation_stats . mark_accepted ( ) <EOL> signals . invitation_accepted . send ( sender = self , <EOL> inviting_user = self . user , <EOL> new_user = new_user ) <EOL> self . delete ( ) <EOL> mark_accepted . alters_data = True <EOL> class InvitationStatsManager ( models . Manager ) : <EOL> def give_invitations ( self , user = None , count = None ) : <EOL> rewarded_users = <NUM_LIT:0> <EOL> invitations_given = <NUM_LIT:0> <EOL> if not isinstance ( count , int ) and not callable ( count ) : <EOL> raise TypeError ( '<STR_LIT>' ) <EOL> if user is None : <EOL> qs = self . get_query_set ( ) <EOL> else : <EOL> qs = self . filter ( user = user ) <EOL> for instance in qs : <EOL> if callable ( count ) : <EOL> c = count ( instance . user ) <EOL> else : <EOL> c = count <EOL> if c : <EOL> instance . add_available ( c ) <EOL> rewarded_users += <NUM_LIT:1> <EOL> invitations_given += c <EOL> return rewarded_users , invitations_given <EOL> def reward ( self , user = None , reward_count = app_settings . INITIAL_INVITATIONS ) : <EOL> def count ( user ) : <EOL> if user . invitation_stats . performance >= app_settings . REWARD_THRESHOLD : <EOL> return reward_count <EOL> return <NUM_LIT:0> <EOL> return self . give_invitations ( user , count ) <EOL> class InvitationStats ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> user = models . OneToOneField ( User , <EOL> related_name = '<STR_LIT>' ) <EOL> available = models . IntegerField ( _ ( u'<STR_LIT>' ) , <EOL> default = app_settings . INITIAL_INVITATIONS ) <EOL> sent = models . IntegerField ( _ ( u'<STR_LIT>' ) , default = <NUM_LIT:0> ) <EOL> accepted = models . IntegerField ( _ ( u'<STR_LIT>' ) , default = <NUM_LIT:0> ) <EOL> objects = InvitationStatsManager ( ) <EOL> class Meta : <EOL> verbose_name = verbose_name_plural = _ ( u'<STR_LIT>' ) <EOL> ordering = ( '<STR_LIT>' , ) <EOL> def __unicode__ ( self ) : <EOL> return _ ( u'<STR_LIT>' ) % { <EOL> '<STR_LIT:username>' : self . user . username } <EOL> @ property <EOL> def performance ( self ) : <EOL> if app_settings . PERFORMANCE_FUNC : <EOL> return app_settings . PERFORMANCE_FUNC ( self ) <EOL> return DEFAULT_PERFORMANCE_CALCULATORS [ app_settings . INVITE_ONLY ] ( self ) <EOL> def add_available ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> self . available = models . F ( '<STR_LIT>' ) + count <EOL> self . save ( ) <EOL> signals . invitation_added . send ( sender = self , user = self . user , count = count ) <EOL> add_available . alters_data = True <EOL> def use ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if app_settings . INVITE_ONLY : <EOL> if self . available - count >= <NUM_LIT:0> : <EOL> self . available = models . F ( '<STR_LIT>' ) - count <EOL> else : <EOL> raise InvitationError ( '<STR_LIT>' ) <EOL> self . sent = models . F ( '<STR_LIT>' ) + count <EOL> self . save ( ) <EOL> use . alters_data = True <EOL> def mark_accepted ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if self . accepted + count > self . sent : <EOL> raise InvitationError ( '<STR_LIT>' '<STR_LIT>' ) <EOL> self . accepted = models . F ( '<STR_LIT>' ) + count <EOL> self . save ( ) <EOL> mark_accepted . alters_data = True <EOL> def create_stats ( sender , instance , created , raw , ** kwargs ) : <EOL> if created and not raw : <EOL> InvitationStats . objects . create ( user = instance ) <EOL> models . signals . post_save . connect ( create_stats , <EOL> sender = User , <EOL> dispatch_uid = '<STR_LIT>' ) </s>
