bgneal@695: """Forms for the user_photos application."""
bgneal@700: import datetime
bgneal@700: 
bgneal@695: from django import forms
bgneal@697: from django.conf import settings
bgneal@695: 
bgneal@700: from core.s3 import S3Bucket
bgneal@700: from core.image_uploader import upload
bgneal@701: from core.services import get_redis_connection
bgneal@696: from user_photos.models import Photo
bgneal@696: 
bgneal@695: 
bgneal@701: def rate_limit(key, limit, seconds):
bgneal@701:     """Use Redis to do a rate limit check. Returns True if the limit is violated
bgneal@701:     and False otherwise.
bgneal@701: 
bgneal@701:     key - the key to check in Redis
bgneal@701:     limit - the rate limit maximum value
bgneal@701:     seconds - the rate limit period in seconds
bgneal@701: 
bgneal@701:     """
bgneal@701:     conn = get_redis_connection()
bgneal@701:     val = conn.incr(key)
bgneal@701:     if val == 1:
bgneal@701:         conn.expire(key, seconds)
bgneal@701:     return val > limit
bgneal@701: 
bgneal@701: 
bgneal@695: class UploadForm(forms.Form):
bgneal@695:     image_file = forms.ImageField()
bgneal@696: 
bgneal@696:     def __init__(self, *args, **kwargs):
bgneal@696:         self.user = kwargs.pop('user')
bgneal@696:         super(UploadForm, self).__init__(*args, **kwargs)
bgneal@696: 
bgneal@701:     def clean(self):
bgneal@701:         cleaned_data = super(UploadForm, self).clean()
bgneal@701: 
bgneal@701:         # rate limit uploads
bgneal@701:         key = 'user_photos:counts:' + self.user.username
bgneal@701:         limit = settings.USER_PHOTOS_RATE_LIMIT
bgneal@701:         if rate_limit(key, *limit):
bgneal@701:             raise forms.ValidationError("You've exceeded your upload quota. "
bgneal@701:                     "Please try again later.")
bgneal@701: 
bgneal@701:         return cleaned_data
bgneal@701: 
bgneal@696:     def save(self):
bgneal@696:         """Processes the image and creates a new Photo object, which is saved to
bgneal@696:         the database. The new Photo instance is returned.
bgneal@696: 
bgneal@696:         This function should only be called if is_valid() returns True.
bgneal@696: 
bgneal@696:         """
bgneal@700:         bucket = S3Bucket(access_key=settings.USER_PHOTOS_ACCESS_KEY,
bgneal@700:                           secret_key=settings.USER_PHOTOS_SECRET_KEY,
bgneal@700:                           base_url=settings.USER_PHOTOS_BASE_URL,
bgneal@700:                           bucket_name=settings.USER_PHOTOS_BUCKET)
bgneal@700: 
bgneal@700:         now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
bgneal@700:         metadata = {'user': self.user.username, 'date': now}
bgneal@700: 
bgneal@700:         url, thumb_url = upload(fp=self.cleaned_data['image_file'],
bgneal@700:                                 bucket=bucket,
bgneal@700:                                 metadata=metadata,
bgneal@700:                                 new_size=settings.USER_PHOTOS_MAX_SIZE,
bgneal@700:                                 thumb_size=settings.USER_PHOTOS_THUMB_SIZE)
bgneal@700: 
bgneal@696:         photo = Photo(user=self.user, url=url, thumb_url=thumb_url)
bgneal@696:         photo.save()
bgneal@696:         return photo