Esempio n. 1
0
class StickyThread(BaseCanvasModel):
    comment = ForeignKey(Comment, null=False, related_name='sticky_threads')
    curator = ForeignKey(User,
                         blank=True,
                         null=True,
                         default=None,
                         related_name='sticky_threads')
    text = TextField()
    timestamp = UnixTimestampField(default=0)
    sort = IntegerField()

    class Meta:
        ordering = ['sort']

    @classmethod
    def get_or_create(cls, comment):
        try:
            sticky = cls.objects.get(comment=comment.id)
        except cls.DoesNotExist:
            cmt = Comment.objects.get(pk=comment.id)
            sticky = cls(comment=cmt)
            try:
                sticky.sort = 1 + max(
                    cls.objects.values_list('sort', flat=True))
            except ValueError:
                sticky.sort = 1
            sticky.save()
        return sticky
Esempio n. 2
0
class Playback(BaseCanvasModel):
    comment = ForeignKey(QuestComment, related_name='playbacks', null=False)
    viewer = ForeignKey(User, null=False)
    timestamp = UnixTimestampField(default=0)

    class Meta(object):
        unique_together = (
            'comment',
            'viewer',
        )

    @classmethod
    def append(cls, **kwargs):
        """ Ignores dupes. """
        if not 'timestamp' in kwargs:
            kwargs['timestamp'] = Now()

        instance = cls(**kwargs)

        try:
            instance.save()
        except IntegrityError:
            return

        instance.comment.details.force()

        @bgwork.defer
        def playback_action():
            Actions.playback(instance.viewer, instance.comment)

    def to_client(self, **kwargs):
        return {
            'timestamp': self.timestamp,
            'viewer': self.viewer,
        }
Esempio n. 3
0
class IapReceipt(BaseCanvasModel):
    """
    See: http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html
    """
    purchaser = ForeignKey(User, db_index=True, related_name='iap_receipts')
    receipt_data = TextField()
    timestamp = UnixTimestampField()

    product_id = CharField(blank=True, max_length=256)
    version_external_identifier = CharField(blank=True, max_length=256)
    bvrs = CharField(blank=True, max_length=256)
    bid = CharField(blank=True, max_length=256)

    verified = BooleanField(default=False)

    def verify(self):
        try:
            cleaned_data = verify_receipt(self.receipt_data)
        except ValidationError:
            self.verified = False
            self.save()
            raise

        for prop in ['bid', 'bvrs', 'product_id']:
            setattr(self, prop, cleaned_data[prop])

        # Missing in the sandbox.
        if 'version_external_identifier' in cleaned_data:
            self.version_external_identifier = cleaned_data[
                'version_external_identifier']

        self.verified = True
        self.save()
Esempio n. 4
0
class SpotlightedThread(BaseCanvasModel):
    comment = ForeignKey(Comment,
                         null=False,
                         related_name='spotlighted_threads')
    curator = ForeignKey(User,
                         blank=True,
                         null=True,
                         default=None,
                         related_name='spotlighted_threads')
    timestamp = UnixTimestampField(default=0)
    sort = IntegerField()

    class Meta:
        ordering = ['sort']

    @classmethod
    def get_or_create(cls, comment):
        if comment.parent_comment_id:
            comment = comment.parent_comment
        try:
            spotlighted = cls.objects.get(comment=comment.id)
        except cls.DoesNotExist:
            cmt = Comment.objects.get(pk=comment.id)
            spotlighted = cls(comment=cmt)
            spotlighted.sort = 1
            spotlighted.save()
        return spotlighted
Esempio n. 5
0
class MonsterInvite(BaseCanvasModel):
    monster_part = ForeignKey(MonsterPart, null=False, related_name='invites')
    timestamp = UnixTimestampField(null=False)
    used_by = ForeignKey(User, null=True)

    @classmethod
    def get_by_monsterpart(cls, monster_part):
        try:
            invite = cls.objects.get(monster_part=monster_part)
        except cls.DoesNotExist:
            invite = cls(monster_part=monster_part,
                         timestamp=Services.time.time())
            invite.save()
        return invite

    @property
    def code(self):
        str_code = "{0}{1}".format(self.pk, int(self.timestamp))
        return base36encode(int(str_code))

    @property
    def is_used(self):
        return not self.used_by is None

    def claim(self, user):
        self.timestamp = Services.time.time()
        self.used_by = user
        self.save()
Esempio n. 6
0
class Activity(BaseCanvasModel):
    actor = ForeignKey(User, null=True)
    timestamp = UnixTimestampField()
    activity_type = CharField(max_length=255, blank=False)
    data = TextField()
    key = PositiveIntegerField(blank=True, null=True)

    class Meta(object):
        unique_together = ('activity_type', 'key')

    @classmethod
    def from_redis_activity(cls, activity, key=None):
        act = cls()

        if activity.actor:
            act.actor = User.objects.get(pk=activity.actor['id'])

        act.timestamp = activity.timestamp
        act.activity_type = activity.TYPE
        act.key = key
        discard_keys = ['actor', 'ts', 'type']
        base = activity.to_dict()
        act._data = {k: base[k] for k in base.keys() if k not in discard_keys}
        act.data = util.dumps(act._data)
        act.save()
        return act

    def _details(self):
        base = util.loads(self.data)
        base.update({
            'id': self.id,
            'ts': self.timestamp,
            'activity_type': self.activity_type,
        })

        #TODO have a UserDetails for example.com too to get rid of this branch.
        if self.actor:
            if settings.PROJECT == 'canvas':
                base['actor'] = {
                    'id': self.actor.id,
                    'username': self.actor.username,
                }
            elif settings.PROJECT == 'drawquest':
                base['actor'] = UserDetails.from_id(self.actor.id).to_client()

        return base

    @classmethod
    def details_by_id(cls, id):
        return CachedCall(
            "activity:%s:details_v2" % id,
            lambda: cls.objects.get(id=id)._details(),
            30 * 24 * 60 * 60,
        )

    @property
    def details(self):
        return Activity.details_by_id(self.id)
Esempio n. 7
0
class IPBlock(BaseCanvasModel):
    ip = IPAddressField(blank=False, unique=True, db_index=True)
    moderator = ForeignKey(User, null=True, limit_choices_to={'is_staff': True})
    timestamp = UnixTimestampField()
    note = TextField()

    class Meta:
        verbose_name_plural = 'IP blocks'
        verbose_name = 'IP block'
Esempio n. 8
0
class Activity(BaseCanvasModel):
    actor_id = BigIntegerField(blank=True, null=True)
    timestamp = UnixTimestampField()
    activity_type = IntegerField(blank=False)
    data = TextField()
    key = BigIntegerField(blank=True, null=True)

    # Common fields, better to have in SQL than JSON.
    comment_id = BigIntegerField(blank=True, null=True)
    quest_id = BigIntegerField(blank=True, null=True)

    class Meta(object):
        unique_together = ('activity_type', 'key')

    @classmethod
    def from_redis_activity(cls, activity, key=None):
        act = cls()

        activity_data = activity.to_dict()

        if activity.actor:
            act.actor_id = int(activity.actor['id'])

        act.quest_id = activity_data.get('quest_id')
        act.comment_id = activity_data.get('comment_id')

        act.timestamp = activity.timestamp
        act.activity_type = ACTIVITY_TYPE_IDS[activity.TYPE]
        act.key = key
        discard_keys = ['actor', 'ts', 'type', 'quest_id', 'comment_id']
        act._data = {
            k: activity_data[k]
            for k in activity_data.keys() if k not in discard_keys
        }
        act.data = util.dumps(act._data)
        act.save()

        return act

    def _details(self):
        base = util.loads(self.data)
        base.update({
            'id':
            self.id,
            'ts':
            self.timestamp,
            'activity_type':
            dict((v, k)
                 for k, v in ACTIVITY_TYPE_IDS.items())[self.activity_type],
        })

        if self.quest_id:
            base['quest_id'] = self.quest_id

        if self.comment_id:
            base['comment_id'] = self.comment_id

        #TODO have a UserDetails for example.com too to get rid of this branch.
        if self.actor_id:
            base['actor'] = UserDetails.from_id(self.actor_id).to_client()

        return base

    @classmethod
    def details_by_id(cls, id, **kwargs):
        return CachedCall(
            'activity:{}:details_v3'.format(id),
            lambda: cls.objects.get(id=id)._details(),
            10 * 24 * 60 * 60,
        )

    @property
    def details(self):
        return self.details_by_id(self.id)
Esempio n. 9
0
class ScheduledQuest(BaseCanvasModel):
    quest = ForeignKey('Quest', null=False)
    curator = ForeignKey(User, blank=True, null=True, default=None, related_name='scheduled_quests')
    timestamp = UnixTimestampField(default=0)
    appeared_on = UnixTimestampField(null=True, db_index=True)
    sort = IntegerField()

    class Meta:
        ordering = ['-appeared_on']

    @classmethod
    def get_or_create(cls, quest):
        if quest.parent_comment_id:
            quest = quest.parent_comment

        try:
            return cls.objects.get(quest=quest.id)
        except cls.DoesNotExist:
            return cls.objects.create(quest=Quest.objects.get(pk=quest.id), sort=1)

    @classmethod
    def archived(cls, select_quests=False):
        qs = cls.objects
        if select_quests:
            qs = qs.select_related('quest')

        current_quest_id = redis.get('dq:current_scheduled_quest')
        if current_quest_id:
            qs = qs.exclude(id=current_quest_id)

        return qs.exclude(appeared_on__isnull=True).order_by('-appeared_on')

    @classmethod
    def unarchived(cls):
        return cls.objects.filter(appeared_on__isnull=True).order_by('sort')

    def _publish_quest_of_the_day(self):
        signals.current_quest_changed.send(ScheduledQuest, instance=self)

        RealtimeChannel('qotd', 1).publish({'quest_id': self.quest_id})

        push_notification('quest_of_the_day',
                          _(u"Today's Quest: %(quest_title)s" % {'quest_title': self.quest.title}),
                          extra_metadata={'quest_id': self.quest.id},
                          badge=1)

    def set_as_current_quest(self):
        redis.set('dq:current_scheduled_quest', self.id)
        self.appeared_on = Services.time.time()
        self.save()
        self.quest.details.force()
        self._publish_quest_of_the_day()

    @classmethod
    def rollover_next_quest(cls):
        """ Sets the next scheduled quest as the currently active one / quest of the day. """
        try:
            cls.unarchived().order_by('sort')[0].set_as_current_quest()
        except IndexError:
            cls.archived().exclude(quest__title='Give him a smile!').order_by('appeared_on')[0].set_as_current_quest()

    @classmethod
    def current_scheduled_quest(cls):
        """ The `ScheduledQuest` instance representing the current quest of the day. """
        scheduled_quest_id = redis.get('dq:current_scheduled_quest')
        if scheduled_quest_id:
            return cls.objects.get(id=scheduled_quest_id)