Merge branch 'master' of https://github.com/FinalsClub/karmaworld
[oweals/karmaworld.git] / karmaworld / apps / notes / models.py
1 #!/usr/bin/env python
2 # -*- coding:utf8 -*-
3 # Copyright (C) 2012  FinalsClub Foundation
4
5 """
6     Models for the notes django app.
7     Contains only the minimum for handling files and their representation
8 """
9 import datetime
10
11 from django.conf import settings
12 from django.core.files.storage import FileSystemStorage
13 from django.db import models
14 from django.template import defaultfilters
15 from taggit.managers import TaggableManager
16 from oauth2client.client import Credentials
17
18 from karmaworld.apps.courses.models import Course
19
20 try:
21     from secrets.drive import GOOGLE_USER
22 except:
23     GOOGLE_USER = u'admin@karmanotes.org'
24
25 fs = FileSystemStorage(location=settings.MEDIA_ROOT)
26
27 class Note(models.Model):
28     """ A django model representing an uploaded file and associated metadata.
29     """
30     UNKNOWN_FILE = '???'
31     FILE_TYPE_CHOICES = (
32         ('doc', 'MS Word compatible file (.doc, .docx, .rtf, .odf)'),
33         ('img', 'Scan or picture of notes'),
34         ('pdf', 'PDF file'),
35         (UNKNOWN_FILE, 'Unknown file'),
36     )
37
38     course          = models.ForeignKey(Course)
39     # Tagging system
40     tags            = TaggableManager(blank=True)
41
42     name            = models.CharField(max_length=255, blank=True, null=True)
43     slug            = models.SlugField(max_length=255, null=True)
44     year            = models.IntegerField(blank=True, null=True, 
45                         default=datetime.datetime.utcnow().year)
46     desc            = models.TextField(max_length=511, blank=True, null=True)
47     uploaded_at     = models.DateTimeField(null=True, default=datetime.datetime.utcnow)
48
49     file_type       = models.CharField(max_length=15,
50                             choices=FILE_TYPE_CHOICES,
51                             default=UNKNOWN_FILE,
52                             blank=True, null=True)
53
54     # Upload files to MEDIA_ROOT/notes/YEAR/MONTH/DAY, 2012/10/30/filename
55     note_file       = models.FileField(
56                             storage=fs,
57                             upload_to="notes/%Y/%m/%j/",
58                             blank=True, null=True)
59
60     ## post gdrive conversion data
61     embed_url       = models.URLField(max_length=1024, blank=True, null=True)
62     download_url    = models.URLField(max_length=1024, blank=True, null=True)
63     # for word processor documents
64     html            = models.TextField(blank=True, null=True)
65     text            = models.TextField(blank=True, null=True)
66
67
68     class Meta:
69         """ Sort files by most recent first """
70         ordering = ['-uploaded_at']
71
72
73     def __unicode__(self):
74         return u"{0}: {1} -- {2}".format(self.file_type, self.name, self.uploaded_at)
75
76     def save(self, *args, **kwargs):
77         """ override built-in save to ensure contextual self.name """
78         # TODO: If self.name isn't set, generate one based on uploaded_name
79         # if we fail to set the Note.name earlier than this, use the saved filename
80
81         # only generate a slug if the name has been set, and slug hasn't
82         if not self.slug and self.name:
83             slug = defaultfilters.slugify(self.name)
84             cursor = Note.objects.filter(slug=slug)
85             # If there are no other notes with this slug, then the slug does not need an id
86             if cursor.count() == 0:
87                 self.slug = slug
88             else:
89                 super(Note, self).save(*args, **kwargs) # generate self.id
90                 self.slug = defaultfilters.slugify("%s %s" % (self.name, self.id))
91             super(Note, self).save(*args, **kwargs)
92
93         # Check if Note.uploaded_at is after Course.updated_at
94         if self.uploaded_at and self.uploaded_at > self.course.updated_at:
95             self.course.updated_at = self.uploaded_at
96             # if it is, update Course.updated_at
97             self.course.save()
98
99         super(Note, self).save(*args, **kwargs)
100
101     def get_absolute_url(self):
102         """ Resolve note url, use 'note' route and slug if slug
103             otherwise use note.id
104         """
105         if self.slug is not None:
106             # return a url ending in slug
107             return u"/{0}/{1}/{2}".format(self.course.school.slug, self.course.slug, self.slug)
108         else:
109             # return a url ending in id
110             return u"/{0}/{1}/{2}".format(self.course.school.slug, self.course.slug, self.id)
111
112
113 class DriveAuth(models.Model):
114     """ stored google drive authentication and refresh token
115         used for interacting with google drive """
116
117     email = models.EmailField(default=GOOGLE_USER)
118     credentials = models.TextField() # JSON of Oauth2Credential object
119     stored_at = models.DateTimeField(auto_now=True)
120
121
122     @staticmethod
123     def get(email=GOOGLE_USER):
124         """ Staticmethod for getting the singleton DriveAuth object """
125         # FIXME: this is untested
126         return DriveAuth.objects.filter(email=email).reverse()[0]
127
128
129     def store(self, creds):
130         """ Transform an existing credentials object to a db serialized """
131         self.email = creds.id_token['email']
132         self.credentials = creds.to_json()
133         self.save()
134
135
136     def transform_to_cred(self):
137         """ take stored credentials and produce a Credentials object """
138         return Credentials.new_from_json(self.credentials)
139
140
141     def __unicode__(self):
142         return u'Gdrive auth for %s created/updated at %s' % \
143                     (self.email, self.stored_at)