gremmie@1: """ gremmie@1: Models for the gcalendar application. bgneal@456: gremmie@1: """ bgneal@458: import datetime bgneal@458: gremmie@1: from django.db import models gremmie@1: from django.db.models import Q gremmie@1: from django.contrib.auth.models import User bgneal@124: bgneal@128: from core.markup import site_markup bgneal@228: import forums.tools bgneal@458: from gcalendar.oauth import serialize_token, deserialize_token gremmie@1: gremmie@1: bgneal@228: GIG_FORUM_SLUG = "gigs" bgneal@228: gremmie@1: class PendingEventManager(models.Manager): gremmie@1: """A manager for pending events.""" gremmie@1: gremmie@1: def get_query_set(self): gremmie@1: """Returns a queryset of events that have been approved to update gremmie@1: the Google calendar.""" gremmie@1: return super(PendingEventManager, self).get_query_set().filter( bgneal@456: Q(status=Event.NEW_APRV) | bgneal@456: Q(status=Event.EDIT_APRV) | gremmie@1: Q(status=Event.DEL_APRV) gremmie@1: ) gremmie@1: gremmie@1: gremmie@1: class Event(models.Model): gremmie@1: """Model to represent calendar events.""" gremmie@1: gremmie@1: # Event status codes: gremmie@1: (NEW, NEW_APRV, EDIT_REQ, EDIT_APRV, DEL_REQ, DEL_APRV, ON_CAL) = range(7) gremmie@1: gremmie@1: STATUS_CHOICES = ( gremmie@1: (NEW, 'New'), gremmie@1: (NEW_APRV, 'New Approved'), gremmie@1: (EDIT_REQ, 'Edit Request'), gremmie@1: (EDIT_APRV, 'Edit Approved'), gremmie@1: (DEL_REQ, 'Delete Request'), gremmie@1: (DEL_APRV, 'Delete Approved'), gremmie@1: (ON_CAL, 'On Calendar'), gremmie@1: ) gremmie@1: gremmie@1: user = models.ForeignKey(User) gremmie@1: what = models.CharField(max_length=255) gremmie@1: start_date = models.DateField() gremmie@1: start_time = models.TimeField(null=True, blank=True) gremmie@1: end_date = models.DateField() gremmie@1: end_time = models.TimeField(null=True, blank=True) gremmie@1: time_zone = models.CharField(max_length=64, blank=True) gremmie@1: all_day = models.BooleanField(default=False) gremmie@1: where = models.CharField(max_length=255, blank=True) gremmie@1: description = models.TextField(blank=True) gremmie@1: html = models.TextField(blank=True) gremmie@1: date_submitted = models.DateTimeField(auto_now_add=True) gremmie@1: google_id = models.CharField(max_length=255, blank=True) bgneal@572: google_url = models.URLField(max_length=255, blank=True) bgneal@228: status = models.SmallIntegerField(choices=STATUS_CHOICES, default=NEW, bgneal@228: db_index=True) bgneal@228: create_forum_thread = models.BooleanField(default=False) gremmie@1: gremmie@1: objects = models.Manager() gremmie@1: pending_events = PendingEventManager() gremmie@1: gremmie@1: def __unicode__(self): gremmie@1: return self.what gremmie@1: gremmie@1: class Meta: gremmie@1: ordering = ('-date_submitted', ) gremmie@1: gremmie@1: def save(self, *args, **kwargs): bgneal@128: self.html = site_markup(self.description) gremmie@1: super(Event, self).save(*args, **kwargs) gremmie@1: bgneal@139: def is_approved(self): bgneal@139: return self.status not in (self.NEW, self.EDIT_REQ, self.DEL_REQ) bgneal@139: is_approved.boolean = True gremmie@1: bgneal@228: def google_html(self): bgneal@228: """Returns a HTML tag to the event if it exits.""" bgneal@228: if self.google_url: bgneal@228: return u'On Google' % self.google_url bgneal@228: return u'' bgneal@228: google_html.allow_tags = True bgneal@228: google_html.short_description = 'Google Link' bgneal@228: bgneal@228: def notify_on_calendar(self): bgneal@228: """ bgneal@228: This function should be called when the event has been added to the bgneal@228: Google calendar for the first time. This gives us a chance to perform bgneal@228: any first-time processing, like creating a forum thread. bgneal@228: """ bgneal@228: if self.create_forum_thread: bgneal@228: topic_name = '%s: %s' % (self.start_date.strftime('%m/%d/%Y'), bgneal@228: self.what) bgneal@228: post_body = "%s\n\n[Link to event on Google Calendar](%s)" % ( bgneal@228: self.description, self.google_url) bgneal@228: bgneal@228: forums.tools.create_topic( bgneal@228: forum_slug=GIG_FORUM_SLUG, bgneal@456: user=self.user, bgneal@228: topic_name=topic_name, bgneal@228: post_body=post_body) bgneal@228: bgneal@228: self.create_forum_thread = False bgneal@228: self.save() bgneal@456: bgneal@456: bgneal@458: class AccessTokenManager(models.Manager): bgneal@458: """ bgneal@458: A manager for the AccessToken table. Only one access token is saved in the bgneal@458: database. This manager provides a convenience method to either return that bgneal@458: access token or a brand new one. bgneal@458: bgneal@458: """ bgneal@458: def get_token(self): bgneal@458: try: bgneal@458: token = self.get(pk=1) bgneal@458: except AccessToken.DoesNotExist: bgneal@458: token = AccessToken() bgneal@458: bgneal@458: return token bgneal@458: bgneal@458: bgneal@456: class AccessToken(models.Model): bgneal@456: """ bgneal@456: This model represents serialized OAuth access tokens for reading and bgneal@456: updating the Google Calendar. bgneal@456: bgneal@456: """ bgneal@456: auth_date = models.DateTimeField() bgneal@456: token = models.TextField() bgneal@456: bgneal@458: objects = AccessTokenManager() bgneal@458: bgneal@456: def __unicode__(self): bgneal@456: return u'Access token created on ' + unicode(self.auth_date) bgneal@456: bgneal@458: def update(self, access_token, auth_date=None): bgneal@458: """ bgneal@458: This function updates the AccessToken object with the input parameters: bgneal@458: access_token - an access token from Google's OAuth dance bgneal@458: auth_date - a datetime or None. If None, now() is used. bgneal@458: bgneal@458: """ bgneal@458: self.auth_date = auth_date if auth_date else datetime.datetime.now() bgneal@458: self.token = serialize_token(access_token) bgneal@458: bgneal@458: def access_token(self): bgneal@458: """ bgneal@458: This function returns a Google OAuth access token by deserializing the bgneal@458: token field from the database. bgneal@458: If the token attribute is empty, None is returned. bgneal@458: bgneal@458: """ bgneal@458: return deserialize_token(self.token) if self.token else None