2012-08-28 18:44:51 +02:00
|
|
|
from django.db import models
|
|
|
|
from django.contrib.auth.models import User
|
2012-08-31 16:11:23 +02:00
|
|
|
from django.db.models import Q
|
2012-08-28 18:44:51 +02:00
|
|
|
from django.db.models.signals import post_save
|
2012-09-04 23:20:21 +02:00
|
|
|
import hashlib
|
2012-08-28 18:44:51 +02:00
|
|
|
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
def get_display_recipient(recipient):
|
|
|
|
"""
|
|
|
|
recipient: an instance of Recipient.
|
|
|
|
|
|
|
|
returns: an appropriate string describing the recipient (the class
|
|
|
|
name, for a class, or the username, for a user).
|
|
|
|
"""
|
|
|
|
if recipient.type == "class":
|
2012-09-04 22:22:06 +02:00
|
|
|
zephyr_class = ZephyrClass.objects.get(pk=recipient.type_id)
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
return zephyr_class.name
|
2012-09-04 23:20:21 +02:00
|
|
|
elif recipient.type == "huddle":
|
2012-09-05 21:55:40 +02:00
|
|
|
user_list = [UserProfile.objects.get(user=s.userprofile) for s in
|
|
|
|
Subscription.objects.filter(recipient=recipient)]
|
2012-09-04 23:20:21 +02:00
|
|
|
return [{'name': user.user.username} for user in user_list]
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
else:
|
2012-09-04 22:22:06 +02:00
|
|
|
user = User.objects.get(pk=recipient.type_id)
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
return user.username
|
|
|
|
|
2012-08-28 22:56:21 +02:00
|
|
|
callback_table = {}
|
|
|
|
|
2012-09-05 21:49:56 +02:00
|
|
|
class Realm(models.Model):
|
|
|
|
domain = models.CharField(max_length=40)
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return "<Realm: %s %s>" % (self.domain, self.id)
|
|
|
|
def __str__(self):
|
|
|
|
return self.__repr__()
|
|
|
|
|
2012-08-28 18:44:51 +02:00
|
|
|
class UserProfile(models.Model):
|
|
|
|
user = models.OneToOneField(User)
|
|
|
|
pointer = models.IntegerField()
|
2012-09-05 21:49:56 +02:00
|
|
|
realm = models.ForeignKey(Realm)
|
2012-08-28 18:44:51 +02:00
|
|
|
|
2012-08-28 22:56:21 +02:00
|
|
|
# The user receives this message
|
|
|
|
def receive(self, message):
|
|
|
|
global callback_table
|
|
|
|
|
|
|
|
# Should also store in permanent database the receipt
|
2012-09-07 17:04:41 +02:00
|
|
|
um = UserMessage(user_profile=self, message=message)
|
|
|
|
um.save()
|
|
|
|
|
2012-08-28 22:56:21 +02:00
|
|
|
for cb in callback_table.get(self.user.id, []):
|
|
|
|
cb([message])
|
|
|
|
|
|
|
|
callback_table[self.user.id] = []
|
|
|
|
|
|
|
|
def add_callback(self, cb, last_received):
|
|
|
|
global callback_table
|
|
|
|
|
2012-09-07 19:51:54 +02:00
|
|
|
new_zephyrs = [um.message for um in
|
|
|
|
UserMessage.objects.filter(user_profile=self,
|
|
|
|
message__id__gt=last_received)]
|
2012-09-05 16:43:20 +02:00
|
|
|
|
2012-08-28 22:56:21 +02:00
|
|
|
if new_zephyrs:
|
|
|
|
return cb(new_zephyrs)
|
|
|
|
callback_table.setdefault(self.user.id, []).append(cb)
|
|
|
|
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
def __repr__(self):
|
2012-09-05 21:49:56 +02:00
|
|
|
return "<UserProfile: %s %s>" % (self.user.username, self.realm)
|
|
|
|
def __str__(self):
|
|
|
|
return self.__repr__()
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
|
2012-09-05 21:49:56 +02:00
|
|
|
def create_user_profile(user, realm):
|
2012-08-29 17:50:36 +02:00
|
|
|
"""When creating a new user, make a profile for him or her."""
|
2012-09-05 21:49:56 +02:00
|
|
|
if not UserProfile.objects.filter(user=user):
|
|
|
|
profile = UserProfile(user=user, pointer=-1, realm_id=realm.id)
|
2012-08-31 16:58:09 +02:00
|
|
|
profile.save()
|
|
|
|
# Auto-sub to the ability to receive personals.
|
2012-09-04 22:22:06 +02:00
|
|
|
recipient = Recipient(type_id=profile.pk, type="personal")
|
2012-08-31 16:58:09 +02:00
|
|
|
recipient.save()
|
2012-09-05 21:55:40 +02:00
|
|
|
Subscription(userprofile=profile, recipient=recipient).save()
|
2012-08-29 17:50:36 +02:00
|
|
|
|
2012-08-28 18:44:51 +02:00
|
|
|
class ZephyrClass(models.Model):
|
|
|
|
name = models.CharField(max_length=30)
|
2012-09-05 22:30:50 +02:00
|
|
|
realm = models.ForeignKey(Realm)
|
2012-08-28 18:44:51 +02:00
|
|
|
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
def __repr__(self):
|
|
|
|
return "<ZephyrClass: %s>" % (self.name,)
|
2012-09-07 17:04:41 +02:00
|
|
|
def __str__(self):
|
|
|
|
return self.__repr__()
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
|
2012-09-07 19:24:54 +02:00
|
|
|
def create_zephyr_class(name, realm):
|
|
|
|
zephyr_class = ZephyrClass(name=name, realm=realm)
|
|
|
|
zephyr_class.save()
|
|
|
|
|
|
|
|
recipient = Recipient(type_id=zephyr_class.id, type="class")
|
|
|
|
recipient.save()
|
|
|
|
return (zephyr_class, recipient)
|
|
|
|
|
2012-08-28 21:27:42 +02:00
|
|
|
class Recipient(models.Model):
|
2012-09-04 22:22:06 +02:00
|
|
|
type_id = models.IntegerField()
|
2012-08-28 21:27:42 +02:00
|
|
|
type = models.CharField(max_length=30)
|
2012-09-04 23:20:21 +02:00
|
|
|
# Valid types are {personal, class, huddle}
|
2012-08-28 21:27:42 +02:00
|
|
|
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
def __repr__(self):
|
|
|
|
display_recipient = get_display_recipient(self)
|
2012-09-04 22:22:06 +02:00
|
|
|
return "<Recipient: %s (%d, %s)>" % (display_recipient, self.type_id, self.type)
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
|
2012-08-28 18:44:51 +02:00
|
|
|
class Zephyr(models.Model):
|
|
|
|
sender = models.ForeignKey(UserProfile)
|
2012-09-04 23:20:21 +02:00
|
|
|
recipient = models.ForeignKey(Recipient)
|
2012-08-28 18:44:51 +02:00
|
|
|
instance = models.CharField(max_length=30)
|
|
|
|
content = models.CharField(max_length=200)
|
|
|
|
pub_date = models.DateTimeField('date published')
|
|
|
|
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
def __repr__(self):
|
|
|
|
display_recipient = get_display_recipient(self.recipient)
|
|
|
|
return "<Zephyr: %s / %s / %r>" % (display_recipient, self.instance, self.sender)
|
2012-09-07 17:04:41 +02:00
|
|
|
def __str__(self):
|
|
|
|
return self.__repr__()
|
Give our models meaningful reprs.
>>> from zephyr.models import UserProfile, Recipient, Zephyr, ZephyrClass
>>> for klass in [UserProfile, Recipient, Zephyr, ZephyrClass]:
... print klass.objects.all()[:2]
...
[<UserProfile: othello>, <UserProfile: iago>]
[<Recipient: Verona (1, class)>, <Recipient: Denmark (2, class)>]
[<Zephyr: Scotland / Scotland3 / <UserProfile: prospero>>, <Zephyr: Venice / Venice3 / <UserProfile: iago>>]
[<ZephyrClass: Verona>, <ZephyrClass: Denmark>]
(imported from commit 9998ffe40800213a5425990d6e85f5c5a43a5355)
2012-08-29 16:15:06 +02:00
|
|
|
|
2012-08-30 19:56:15 +02:00
|
|
|
def to_dict(self):
|
|
|
|
return {'id' : self.id,
|
|
|
|
'sender' : self.sender.user.username,
|
|
|
|
'type' : self.recipient.type,
|
|
|
|
'display_recipient': get_display_recipient(self.recipient),
|
|
|
|
'instance' : self.instance,
|
|
|
|
'content' : self.content }
|
|
|
|
|
2012-09-07 17:04:41 +02:00
|
|
|
class UserMessage(models.Model):
|
|
|
|
user_profile = models.ForeignKey(UserProfile)
|
|
|
|
message = models.ForeignKey(Zephyr)
|
|
|
|
# We're not using the archived field for now, but create it anyway
|
|
|
|
# since this table will be an unpleasant one to do schema changes
|
|
|
|
# on later
|
|
|
|
archived = models.BooleanField()
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
display_recipient = get_display_recipient(self.message.recipient)
|
|
|
|
return "<UserMessage: %s / %s>" % (display_recipient, self.user_profile.user.username)
|
|
|
|
|
2012-08-28 22:56:21 +02:00
|
|
|
def send_zephyr(**kwargs):
|
|
|
|
zephyr = kwargs["instance"]
|
|
|
|
if zephyr.recipient.type == "personal":
|
2012-09-04 22:22:06 +02:00
|
|
|
recipients = UserProfile.objects.filter(Q(user=zephyr.recipient.type_id) | Q(user=zephyr.sender))
|
2012-08-31 16:58:09 +02:00
|
|
|
# For personals, you send out either 1 or 2 copies of the zephyr, for
|
|
|
|
# personals to yourself or to someone else, respectively.
|
|
|
|
assert((len(recipients) == 1) or (len(recipients) == 2))
|
2012-09-04 23:20:21 +02:00
|
|
|
elif zephyr.recipient.type == "class" or zephyr.recipient.type == "huddle":
|
2012-09-05 21:55:40 +02:00
|
|
|
recipients = [UserProfile.objects.get(user=s.userprofile) for
|
|
|
|
s in Subscription.objects.filter(recipient=zephyr.recipient, active=True)]
|
2012-08-28 22:56:21 +02:00
|
|
|
else:
|
|
|
|
raise
|
|
|
|
for recipient in recipients:
|
|
|
|
recipient.receive(zephyr)
|
|
|
|
|
|
|
|
post_save.connect(send_zephyr, sender=Zephyr)
|
|
|
|
|
2012-08-29 17:50:36 +02:00
|
|
|
class Subscription(models.Model):
|
2012-09-05 21:55:40 +02:00
|
|
|
userprofile = models.ForeignKey(UserProfile)
|
|
|
|
recipient = models.ForeignKey(Recipient)
|
2012-08-30 18:03:58 +02:00
|
|
|
active = models.BooleanField(default=True)
|
2012-08-29 17:50:36 +02:00
|
|
|
|
|
|
|
def __repr__(self):
|
2012-09-05 21:55:40 +02:00
|
|
|
return "<Subscription: %r -> %r>" % (self.userprofile, self.recipient)
|
2012-09-07 17:04:41 +02:00
|
|
|
def __str__(self):
|
|
|
|
return self.__repr__()
|
2012-08-28 22:56:21 +02:00
|
|
|
|
2012-09-04 23:20:21 +02:00
|
|
|
class Huddle(models.Model):
|
|
|
|
huddle_hash = models.CharField(max_length=40)
|
|
|
|
|
|
|
|
def get_huddle(id_list):
|
2012-09-05 17:38:09 +02:00
|
|
|
id_list = sorted(set(id_list))
|
2012-09-05 17:41:53 +02:00
|
|
|
hash_key = ",".join(str(x) for x in id_list)
|
2012-09-04 23:20:21 +02:00
|
|
|
huddle_hash = hashlib.sha1(hash_key).hexdigest()
|
|
|
|
if Huddle.objects.filter(huddle_hash=huddle_hash):
|
|
|
|
return Huddle.objects.get(huddle_hash=huddle_hash)
|
|
|
|
else:
|
|
|
|
# since we don't have one, make a new huddle
|
|
|
|
huddle = Huddle(huddle_hash = huddle_hash)
|
|
|
|
huddle.save()
|
|
|
|
recipient = Recipient(type_id=huddle.pk, type="huddle")
|
|
|
|
recipient.save()
|
|
|
|
|
|
|
|
# Add subscriptions
|
|
|
|
for uid in id_list:
|
2012-09-05 21:55:40 +02:00
|
|
|
s = Subscription(recipient = recipient,
|
|
|
|
userprofile = UserProfile.objects.get(id=uid))
|
2012-09-04 23:20:21 +02:00
|
|
|
s.save()
|
|
|
|
return huddle
|
|
|
|
|
2012-08-28 22:56:21 +02:00
|
|
|
def filter_by_subscriptions(zephyrs, user):
|
|
|
|
userprofile = UserProfile.objects.get(user=user)
|
|
|
|
subscribed_zephyrs = []
|
2012-09-07 19:53:24 +02:00
|
|
|
subscriptions = [sub.recipient for sub in
|
|
|
|
Subscription.objects.filter(userprofile=userprofile, active=True)]
|
2012-08-28 22:56:21 +02:00
|
|
|
for zephyr in zephyrs:
|
2012-09-07 19:53:24 +02:00
|
|
|
# If you are subscribed to the personal or class, or if you
|
|
|
|
# sent the personal, you can see the zephyr.
|
2012-08-28 22:56:21 +02:00
|
|
|
if (zephyr.recipient in subscriptions) or \
|
2012-09-07 19:53:24 +02:00
|
|
|
(zephyr.recipient.type == "personal" and
|
|
|
|
zephyr.sender == userprofile):
|
2012-08-28 22:56:21 +02:00
|
|
|
subscribed_zephyrs.append(zephyr)
|
|
|
|
|
|
|
|
return subscribed_zephyrs
|