예제 #1
0
class Profile(models.Model):
    user = models.OneToOneField(User, unique=True, related_name="profile")
    is_premium = models.BooleanField(default=False)
    preferences = models.TextField(default="{}")
    view_settings = models.TextField(default="{}")
    collapsed_folders = models.TextField(default="[]")
    feed_pane_size = models.IntegerField(default=240)
    tutorial_finished = models.BooleanField(default=False)
    last_seen_on = models.DateTimeField(default=datetime.datetime.now)
    last_seen_ip = models.CharField(max_length=50, blank=True, null=True)
    timezone = TimeZoneField(default="America/New_York")
    secret_token = models.CharField(max_length=12, blank=True, null=True)

    def __unicode__(self):
        return "%s" % self.user

    def save(self, *args, **kwargs):
        if not self.secret_token:
            self.secret_token = generate_secret_token(self.user.username, 12)
        super(Profile, self).save(*args, **kwargs)

    def activate_premium(self):
        self.is_premium = True
        self.save()

        subs = UserSubscription.objects.filter(user=self.user)
        for sub in subs:
            sub.active = True
            try:
                sub.save()
                sub.feed.setup_feed_for_premium_subscribers()
            except IntegrityError, Feed.DoesNotExist:
                pass

        self.queue_new_feeds()

        logging.user(
            self.user,
            "~BY~SK~FW~SBNEW PREMIUM ACCOUNT! WOOHOO!!! ~FR%s subscriptions~SN!"
            % (subs.count()))
        message = """Woohoo!
        
User: %(user)s
Feeds: %(feeds)s

Sincerely,
NewsBlur""" % {
            'user': self.user.username,
            'feeds': subs.count()
        }
        mail_admins('New premium account', message, fail_silently=True)
예제 #2
0
class Profile(models.Model):
    user = models.OneToOneField(User, unique=True, related_name="profile")
    is_premium = models.BooleanField(default=False)
    premium_expire = models.DateTimeField(blank=True, null=True)
    send_emails = models.BooleanField(default=True)
    preferences = models.TextField(default="{}")
    view_settings = models.TextField(default="{}")
    collapsed_folders = models.TextField(default="[]")
    feed_pane_size = models.IntegerField(default=242)
    tutorial_finished = models.BooleanField(default=False)
    hide_getting_started = models.NullBooleanField(default=False,
                                                   null=True,
                                                   blank=True)
    has_setup_feeds = models.NullBooleanField(default=False,
                                              null=True,
                                              blank=True)
    has_found_friends = models.NullBooleanField(default=False,
                                                null=True,
                                                blank=True)
    has_trained_intelligence = models.NullBooleanField(default=False,
                                                       null=True,
                                                       blank=True)
    last_seen_on = models.DateTimeField(default=datetime.datetime.now)
    last_seen_ip = models.CharField(max_length=50, blank=True, null=True)
    dashboard_date = models.DateTimeField(default=datetime.datetime.now)
    timezone = TimeZoneField(default="America/New_York")
    secret_token = models.CharField(max_length=12, blank=True, null=True)
    stripe_4_digits = models.CharField(max_length=4, blank=True, null=True)
    stripe_id = models.CharField(max_length=24, blank=True, null=True)

    def __unicode__(self):
        return "%s <%s> (Premium: %s)" % (self.user, self.user.email,
                                          self.is_premium)

    @property
    def unread_cutoff(self, force_premium=False):
        if self.is_premium or force_premium:
            return datetime.datetime.utcnow() - datetime.timedelta(
                days=settings.DAYS_OF_UNREAD)

        return datetime.datetime.utcnow() - datetime.timedelta(
            days=settings.DAYS_OF_UNREAD_FREE)

    @property
    def unread_cutoff_premium(self):
        return datetime.datetime.utcnow() - datetime.timedelta(
            days=settings.DAYS_OF_UNREAD)

    def canonical(self):
        return {
            'is_premium': self.is_premium,
            'preferences': json.decode(self.preferences),
            'tutorial_finished': self.tutorial_finished,
            'hide_getting_started': self.hide_getting_started,
            'has_setup_feeds': self.has_setup_feeds,
            'has_found_friends': self.has_found_friends,
            'has_trained_intelligence': self.has_trained_intelligence,
            'dashboard_date': self.dashboard_date
        }

    def save(self, *args, **kwargs):
        if not self.secret_token:
            self.secret_token = generate_secret_token(self.user.username, 12)
        try:
            super(Profile, self).save(*args, **kwargs)
        except DatabaseError:
            print " ---> Profile not saved. Table isn't there yet."

    def delete_user(self, confirm=False, fast=False):
        if not confirm:
            print " ---> You must pass confirm=True to delete this user."
            return

        try:
            self.cancel_premium()
        except:
            logging.user(
                self.user,
                "~BR~SK~FWError cancelling premium renewal for: %s" %
                self.user.username)

        from apps.social.models import MSocialProfile, MSharedStory, MSocialSubscription
        from apps.social.models import MActivity, MInteraction
        try:
            social_profile = MSocialProfile.objects.get(user_id=self.user.pk)
            logging.user(
                self.user, "Unfollowing %s followings and %s followers" %
                (social_profile.following_count,
                 social_profile.follower_count))
            for follow in social_profile.following_user_ids:
                social_profile.unfollow_user(follow)
            for follower in social_profile.follower_user_ids:
                follower_profile = MSocialProfile.objects.get(user_id=follower)
                follower_profile.unfollow_user(self.user.pk)
            social_profile.delete()
        except MSocialProfile.DoesNotExist:
            logging.user(self.user,
                         " ***> No social profile found. S'ok, moving on.")
            pass

        shared_stories = MSharedStory.objects.filter(user_id=self.user.pk)
        logging.user(self.user,
                     "Deleting %s shared stories" % shared_stories.count())
        for story in shared_stories:
            try:
                if not fast:
                    original_story = MStory.objects.get(
                        story_hash=story.story_hash)
                    original_story.sync_redis()
            except MStory.DoesNotExist:
                pass
            story.delete()

        subscriptions = MSocialSubscription.objects.filter(
            subscription_user_id=self.user.pk)
        logging.user(
            self.user,
            "Deleting %s social subscriptions" % subscriptions.count())
        subscriptions.delete()

        interactions = MInteraction.objects.filter(user_id=self.user.pk)
        logging.user(
            self.user,
            "Deleting %s interactions for user." % interactions.count())
        interactions.delete()

        interactions = MInteraction.objects.filter(with_user_id=self.user.pk)
        logging.user(
            self.user,
            "Deleting %s interactions with user." % interactions.count())
        interactions.delete()

        activities = MActivity.objects.filter(user_id=self.user.pk)
        logging.user(self.user,
                     "Deleting %s activities for user." % activities.count())
        activities.delete()

        activities = MActivity.objects.filter(with_user_id=self.user.pk)
        logging.user(self.user,
                     "Deleting %s activities with user." % activities.count())
        activities.delete()

        starred_stories = MStarredStory.objects.filter(user_id=self.user.pk)
        logging.user(self.user,
                     "Deleting %s starred stories." % starred_stories.count())
        starred_stories.delete()

        logging.user(self.user, "Deleting user: %s" % self.user)
        self.user.delete()

    def check_if_spammer(self):
        feed_opens = UserSubscription.objects.filter(user=self.user)\
                     .aggregate(sum=Sum('feed_opens'))['sum']
        feed_count = UserSubscription.objects.filter(user=self.user).count()

        if not feed_opens and not feed_count:
            return True

    def activate_premium(self):
        from apps.profile.tasks import EmailNewPremium
        EmailNewPremium.delay(user_id=self.user.pk)

        self.is_premium = True
        self.save()
        self.user.is_active = True
        self.user.save()

        subs = UserSubscription.objects.filter(user=self.user)
        for sub in subs:
            if sub.active: continue
            sub.active = True
            try:
                sub.save()
            except (IntegrityError, Feed.DoesNotExist):
                pass

        try:
            scheduled_feeds = [sub.feed.pk for sub in subs]
        except Feed.DoesNotExist:
            scheduled_feeds = []
        logging.user(
            self.user,
            "~SN~FMTasking the scheduling immediate premium setup of ~SB%s~SN feeds..."
            % len(scheduled_feeds))
        SchedulePremiumSetup.apply_async(kwargs=dict(feed_ids=scheduled_feeds))

        self.queue_new_feeds()
        self.setup_premium_history()

        logging.user(
            self.user,
            "~BY~SK~FW~SBNEW PREMIUM ACCOUNT! WOOHOO!!! ~FR%s subscriptions~SN!"
            % (subs.count()))

        return True

    def deactivate_premium(self):
        self.is_premium = False
        self.save()

        subs = UserSubscription.objects.filter(user=self.user)
        for sub in subs:
            sub.active = False
            try:
                sub.save()
                sub.feed.setup_feed_for_premium_subscribers()
            except (IntegrityError, Feed.DoesNotExist):
                pass

        logging.user(
            self.user,
            "~BY~FW~SBBOO! Deactivating premium account: ~FR%s subscriptions~SN!"
            % (subs.count()))

    def activate_free(self):
        if self.user.is_active:
            return

        self.user.is_active = True
        self.user.save()
        self.send_new_user_queue_email()

    def setup_premium_history(self, alt_email=None):
        existing_history = PaymentHistory.objects.filter(user=self.user)
        if existing_history.count():
            print " ---> Deleting existing history: %s payments" % existing_history.count(
            )
            existing_history.delete()

        # Record Paypal payments
        paypal_payments = PayPalIPN.objects.filter(custom=self.user.username,
                                                   txn_type='subscr_payment')
        if not paypal_payments.count():
            paypal_payments = PayPalIPN.objects.filter(
                payer_email=self.user.email, txn_type='subscr_payment')
        if alt_email and not paypal_payments.count():
            paypal_payments = PayPalIPN.objects.filter(
                payer_email=alt_email, txn_type='subscr_payment')
            if paypal_payments.count():
                # Make sure this doesn't happen again, so let's use Paypal's email.
                self.user.email = alt_email
                self.user.save()
        for payment in paypal_payments:
            PaymentHistory.objects.create(user=self.user,
                                          payment_date=payment.payment_date,
                                          payment_amount=payment.payment_gross,
                                          payment_provider='paypal')

        print " ---> Found %s paypal_payments" % len(paypal_payments)

        # Record Stripe payments
        if self.stripe_id:
            stripe.api_key = settings.STRIPE_SECRET
            stripe_customer = stripe.Customer.retrieve(self.stripe_id)
            stripe_payments = stripe.Charge.all(
                customer=stripe_customer.id).data

            existing_history = PaymentHistory.objects.filter(
                user=self.user, payment_provider='stripe')
            if existing_history.count():
                print " ---> Deleting existing history: %s stripe payments" % existing_history.count(
                )
                existing_history.delete()

            for payment in stripe_payments:
                created = datetime.datetime.fromtimestamp(payment.created)
                PaymentHistory.objects.create(user=self.user,
                                              payment_date=created,
                                              payment_amount=payment.amount /
                                              100.0,
                                              payment_provider='stripe')
            print " ---> Found %s stripe_payments" % len(stripe_payments)

        # Calculate payments in last year, then add together
        payment_history = PaymentHistory.objects.filter(user=self.user)
        last_year = datetime.datetime.now() - datetime.timedelta(days=364)
        recent_payments_count = 0
        oldest_recent_payment_date = None
        for payment in payment_history:
            if payment.payment_date > last_year:
                recent_payments_count += 1
                if not oldest_recent_payment_date or payment.payment_date < oldest_recent_payment_date:
                    oldest_recent_payment_date = payment.payment_date
        print " ---> %s payments" % len(payment_history)

        if oldest_recent_payment_date:
            self.premium_expire = (
                oldest_recent_payment_date +
                datetime.timedelta(days=365 * recent_payments_count))
            self.save()

    def refund_premium(self, partial=False):
        refunded = False

        if self.stripe_id:
            stripe.api_key = settings.STRIPE_SECRET
            stripe_customer = stripe.Customer.retrieve(self.stripe_id)
            stripe_payments = stripe.Charge.all(
                customer=stripe_customer.id).data
            if partial:
                stripe_payments[0].refund(amount=1200)
                refunded = 12
            else:
                stripe_payments[0].refund()
                self.cancel_premium()
                refunded = stripe_payments[0].amount / 100
            logging.user(self.user,
                         "~FRRefunding stripe payment: $%s" % refunded)
        else:
            self.cancel_premium()

            paypal_opts = {
                'API_ENVIRONMENT': 'PRODUCTION',
                'API_USERNAME': settings.PAYPAL_API_USERNAME,
                'API_PASSWORD': settings.PAYPAL_API_PASSWORD,
                'API_SIGNATURE': settings.PAYPAL_API_SIGNATURE,
            }
            paypal = PayPalInterface(**paypal_opts)
            transaction = PayPalIPN.objects.filter(
                custom=self.user.username,
                txn_type='subscr_payment').order_by('-payment_date')[0]
            refund = paypal.refund_transaction(transaction.txn_id)
            try:
                refunded = int(float(refund.raw['TOTALREFUNDEDAMOUNT'][0]))
            except KeyError:
                refunded = int(transaction.payment_gross)
            logging.user(self.user,
                         "~FRRefunding paypal payment: $%s" % refunded)

        return refunded

    def cancel_premium(self):
        paypal_cancel = self.cancel_premium_paypal()
        stripe_cancel = self.cancel_premium_stripe()
        return paypal_cancel or stripe_cancel

    def cancel_premium_paypal(self):
        transactions = PayPalIPN.objects.filter(custom=self.user.username,
                                                txn_type='subscr_signup')
        if not transactions:
            return

        paypal_opts = {
            'API_ENVIRONMENT': 'PRODUCTION',
            'API_USERNAME': settings.PAYPAL_API_USERNAME,
            'API_PASSWORD': settings.PAYPAL_API_PASSWORD,
            'API_SIGNATURE': settings.PAYPAL_API_SIGNATURE,
        }
        paypal = PayPalInterface(**paypal_opts)
        transaction = transactions[0]
        profileid = transaction.subscr_id
        try:
            paypal.manage_recurring_payments_profile_status(
                profileid=profileid, action='Cancel')
        except PayPalAPIResponseError:
            logging.user(self.user,
                         "~FRUser ~SBalready~SN canceled Paypal subscription")
        else:
            logging.user(self.user, "~FRCanceling Paypal subscription")

        return True

    def cancel_premium_stripe(self):
        if not self.stripe_id:
            return

        stripe.api_key = settings.STRIPE_SECRET
        stripe_customer = stripe.Customer.retrieve(self.stripe_id)
        try:
            stripe_customer.cancel_subscription()
        except stripe.InvalidRequestError:
            logging.user(self.user, "~FRFailed to cancel Stripe subscription")

        logging.user(self.user, "~FRCanceling Stripe subscription")

        return True

    def queue_new_feeds(self, new_feeds=None):
        if not new_feeds:
            new_feeds = UserSubscription.objects.filter(
                user=self.user, feed__fetched_once=False,
                active=True).values('feed_id')
            new_feeds = list(set([f['feed_id'] for f in new_feeds]))
        logging.user(
            self.user, "~BB~FW~SBQueueing NewFeeds: ~FC(%s) %s" %
            (len(new_feeds), new_feeds))
        size = 4
        for t in (new_feeds[pos:pos + size]
                  for pos in xrange(0, len(new_feeds), size)):
            NewFeeds.apply_async(args=(t, ), queue="new_feeds")

    def refresh_stale_feeds(self, exclude_new=False):
        stale_cutoff = datetime.datetime.now() - datetime.timedelta(days=7)
        stale_feeds = UserSubscription.objects.filter(
            user=self.user, active=True, feed__last_update__lte=stale_cutoff)
        if exclude_new:
            stale_feeds = stale_feeds.filter(feed__fetched_once=True)
        all_feeds = UserSubscription.objects.filter(user=self.user,
                                                    active=True)

        logging.user(
            self.user, "~FG~BBRefreshing stale feeds: ~SB%s/%s" %
            (stale_feeds.count(), all_feeds.count()))

        for sub in stale_feeds:
            sub.feed.fetched_once = False
            sub.feed.save()

        if stale_feeds:
            stale_feeds = list(set([f.feed_id for f in stale_feeds]))
            self.queue_new_feeds(new_feeds=stale_feeds)

    def import_reader_starred_items(self, count=20):
        importer = GoogleReaderImporter(self.user)
        importer.import_starred_items(count=count)

    def send_new_user_email(self):
        if not self.user.email or not self.send_emails:
            return

        user = self.user
        text = render_to_string('mail/email_new_account.txt', locals())
        html = render_to_string('mail/email_new_account.xhtml', locals())
        subject = "Welcome to NewsBlur, %s" % (self.user.username)
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        logging.user(
            self.user,
            "~BB~FM~SBSending email for new user: %s" % self.user.email)

    def send_opml_export_email(self):
        if not self.user.email:
            return

        MSentEmail.objects.get_or_create(receiver_user_id=self.user.pk,
                                         email_type='opml_export')

        exporter = OPMLExporter(self.user)
        opml = exporter.process()

        params = {
            'feed_count':
            UserSubscription.objects.filter(user=self.user).count(),
        }
        user = self.user
        text = render_to_string('mail/email_opml_export.txt', params)
        html = render_to_string('mail/email_opml_export.xhtml', params)
        subject = "Backup OPML file of your NewsBlur sites"
        filename = 'NewsBlur Subscriptions - %s.xml' % datetime.datetime.now(
        ).strftime('%Y-%m-%d')
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.attach(filename, opml, 'text/xml')
        msg.send(fail_silently=True)

        logging.user(
            self.user,
            "~BB~FM~SBSending OPML backup email to: %s" % self.user.email)

    def send_first_share_to_blurblog_email(self, force=False):
        from apps.social.models import MSocialProfile, MSharedStory

        if not self.user.email:
            return

        sent_email, created = MSentEmail.objects.get_or_create(
            receiver_user_id=self.user.pk, email_type='first_share')

        if not created and not force:
            return

        social_profile = MSocialProfile.objects.get(user_id=self.user.pk)
        params = {
            'shared_stories':
            MSharedStory.objects.filter(user_id=self.user.pk).count(),
            'blurblog_url':
            social_profile.blurblog_url,
            'blurblog_rss':
            social_profile.blurblog_rss
        }
        user = self.user
        text = render_to_string('mail/email_first_share_to_blurblog.txt',
                                params)
        html = render_to_string('mail/email_first_share_to_blurblog.xhtml',
                                params)
        subject = "Your shared stories on NewsBlur are available on your Blurblog"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        logging.user(
            self.user,
            "~BB~FM~SBSending first share to blurblog email to: %s" %
            self.user.email)

    def send_new_premium_email(self, force=False):
        subs = UserSubscription.objects.filter(user=self.user)
        message = """Woohoo!
        
User: %(user)s
Feeds: %(feeds)s

Sincerely,
NewsBlur""" % {
            'user': self.user.username,
            'feeds': subs.count()
        }
        mail_admins('New premium account', message, fail_silently=True)

        if not self.user.email or not self.send_emails:
            return

        sent_email, created = MSentEmail.objects.get_or_create(
            receiver_user_id=self.user.pk, email_type='new_premium')

        if not created and not force:
            return

        user = self.user
        text = render_to_string('mail/email_new_premium.txt', locals())
        html = render_to_string('mail/email_new_premium.xhtml', locals())
        subject = "Thanks for going premium on NewsBlur!"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        logging.user(
            self.user,
            "~BB~FM~SBSending email for new premium: %s" % self.user.email)

    def send_forgot_password_email(self, email=None):
        if not self.user.email and not email:
            print "Please provide an email address."
            return

        if not self.user.email and email:
            self.user.email = email
            self.user.save()

        user = self.user
        text = render_to_string('mail/email_forgot_password.txt', locals())
        html = render_to_string('mail/email_forgot_password.xhtml', locals())
        subject = "Forgot your password on NewsBlur?"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        logging.user(
            self.user, "~BB~FM~SBSending email for forgotten password: %s" %
            self.user.email)

    def send_new_user_queue_email(self, force=False):
        if not self.user.email:
            print "Please provide an email address."
            return

        sent_email, created = MSentEmail.objects.get_or_create(
            receiver_user_id=self.user.pk, email_type='new_user_queue')
        if not created and not force:
            return

        user = self.user
        text = render_to_string('mail/email_new_user_queue.txt', locals())
        html = render_to_string('mail/email_new_user_queue.xhtml', locals())
        subject = "Your free account is now ready to go on NewsBlur"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        logging.user(
            self.user,
            "~BB~FM~SBSending email for new user queue: %s" % self.user.email)

    def send_upload_opml_finished_email(self, feed_count):
        if not self.user.email:
            print "Please provide an email address."
            return

        user = self.user
        text = render_to_string('mail/email_upload_opml_finished.txt',
                                locals())
        html = render_to_string('mail/email_upload_opml_finished.xhtml',
                                locals())
        subject = "Your OPML upload is complete. Get going with NewsBlur!"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send()

        logging.user(
            self.user,
            "~BB~FM~SBSending email for OPML upload: %s" % self.user.email)

    def send_import_reader_finished_email(self, feed_count):
        if not self.user.email:
            print "Please provide an email address."
            return

        user = self.user
        text = render_to_string('mail/email_import_reader_finished.txt',
                                locals())
        html = render_to_string('mail/email_import_reader_finished.xhtml',
                                locals())
        subject = "Your Google Reader import is complete. Get going with NewsBlur!"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send()

        logging.user(
            self.user, "~BB~FM~SBSending email for Google Reader import: %s" %
            self.user.email)

    def send_import_reader_starred_finished_email(self, feed_count,
                                                  starred_count):
        if not self.user.email:
            print "Please provide an email address."
            return

        user = self.user
        text = render_to_string(
            'mail/email_import_reader_starred_finished.txt', locals())
        html = render_to_string(
            'mail/email_import_reader_starred_finished.xhtml', locals())
        subject = "Your Google Reader starred stories import is complete. Get going with NewsBlur!"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send()

        logging.user(
            self.user,
            "~BB~FM~SBSending email for Google Reader starred stories import: %s"
            % self.user.email)

    def send_launch_social_email(self, force=False):
        if not self.user.email or not self.send_emails:
            logging.user(
                self.user,
                "~FM~SB~FRNot~FM sending launch social email for user, %s: %s"
                %
                (self.user.email and 'opt-out: ' or 'blank', self.user.email))
            return

        sent_email, created = MSentEmail.objects.get_or_create(
            receiver_user_id=self.user.pk, email_type='launch_social')

        if not created and not force:
            logging.user(
                self.user,
                "~FM~SB~FRNot~FM sending launch social email for user, sent already: %s"
                % self.user.email)
            return

        delta = datetime.datetime.now() - self.last_seen_on
        months_ago = delta.days / 30
        user = self.user
        data = dict(user=user, months_ago=months_ago)
        text = render_to_string('mail/email_launch_social.txt', data)
        html = render_to_string('mail/email_launch_social.xhtml', data)
        subject = "NewsBlur is now a social news reader"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        logging.user(
            self.user,
            "~BB~FM~SBSending launch social email for user: %s months, %s" %
            (months_ago, self.user.email))

    def send_premium_expire_grace_period_email(self, force=False):
        if not self.user.email:
            logging.user(
                self.user,
                "~FM~SB~FRNot~FM~SN sending premium expire grace for user: %s"
                % (self.user))
            return

        emails_sent = MSentEmail.objects.filter(
            receiver_user_id=self.user.pk, email_type='premium_expire_grace')
        day_ago = datetime.datetime.now() - datetime.timedelta(days=360)
        for email in emails_sent:
            if email.date_sent > day_ago and not force:
                logging.user(
                    self.user,
                    "~SN~FMNot sending premium expire grace email, already sent before."
                )
                return

        self.premium_expire = datetime.datetime.now()
        self.save()

        delta = datetime.datetime.now() - self.last_seen_on
        months_ago = delta.days / 30
        user = self.user
        data = dict(user=user, months_ago=months_ago)
        text = render_to_string('mail/email_premium_expire_grace.txt', data)
        html = render_to_string('mail/email_premium_expire_grace.xhtml', data)
        subject = "Your premium account on NewsBlur has one more month!"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        MSentEmail.record(receiver_user_id=self.user.pk,
                          email_type='premium_expire_grace')
        logging.user(
            self.user,
            "~BB~FM~SBSending premium expire grace email for user: %s months, %s"
            % (months_ago, self.user.email))

    def send_premium_expire_email(self, force=False):
        if not self.user.email:
            logging.user(
                self.user,
                "~FM~SB~FRNot~FM sending premium expire for user: %s" %
                (self.user))
            return

        emails_sent = MSentEmail.objects.filter(receiver_user_id=self.user.pk,
                                                email_type='premium_expire')
        day_ago = datetime.datetime.now() - datetime.timedelta(days=360)
        for email in emails_sent:
            if email.date_sent > day_ago and not force:
                logging.user(
                    self.user,
                    "~FM~SBNot sending premium expire email, already sent before."
                )
                return

        delta = datetime.datetime.now() - self.last_seen_on
        months_ago = delta.days / 30
        user = self.user
        data = dict(user=user, months_ago=months_ago)
        text = render_to_string('mail/email_premium_expire.txt', data)
        html = render_to_string('mail/email_premium_expire.xhtml', data)
        subject = "Your premium account on NewsBlur has expired"
        msg = EmailMultiAlternatives(subject,
                                     text,
                                     from_email='NewsBlur <%s>' %
                                     settings.HELLO_EMAIL,
                                     to=['%s <%s>' % (user, user.email)])
        msg.attach_alternative(html, "text/html")
        msg.send(fail_silently=True)

        MSentEmail.record(receiver_user_id=self.user.pk,
                          email_type='premium_expire')
        logging.user(
            self.user,
            "~BB~FM~SBSending premium expire email for user: %s months, %s" %
            (months_ago, self.user.email))

    def autologin_url(self, next=None):
        return reverse('autologin',
                       kwargs={
                           'username': self.user.username,
                           'secret': self.secret_token
                       }) + ('?' + next + '=1' if next else '')
예제 #3
0
class Profile(models.Model):
    user = models.OneToOneField(User, unique=True, related_name="profile")
    is_premium = models.BooleanField(default=False)
    send_emails = models.BooleanField(default=True)
    preferences = models.TextField(default="{}")
    view_settings = models.TextField(default="{}")
    collapsed_folders = models.TextField(default="[]")
    feed_pane_size = models.IntegerField(default=240)
    tutorial_finished = models.BooleanField(default=False)
    hide_getting_started = models.NullBooleanField(default=False,
                                                   null=True,
                                                   blank=True)
    has_setup_feeds = models.NullBooleanField(default=False,
                                              null=True,
                                              blank=True)
    has_found_friends = models.NullBooleanField(default=False,
                                                null=True,
                                                blank=True)
    has_trained_intelligence = models.NullBooleanField(default=False,
                                                       null=True,
                                                       blank=True)
    last_seen_on = models.DateTimeField(default=datetime.datetime.now)
    last_seen_ip = models.CharField(max_length=50, blank=True, null=True)
    dashboard_date = models.DateTimeField(default=datetime.datetime.now)
    timezone = TimeZoneField(default="America/New_York")
    secret_token = models.CharField(max_length=12, blank=True, null=True)
    stripe_4_digits = models.CharField(max_length=4, blank=True, null=True)
    stripe_id = models.CharField(max_length=24, blank=True, null=True)

    def __unicode__(self):
        return "%s <%s> (Premium: %s)" % (self.user, self.user.email,
                                          self.is_premium)

    def to_json(self):
        return {
            'is_premium': self.is_premium,
            'preferences': json.decode(self.preferences),
            'tutorial_finished': self.tutorial_finished,
            'hide_getting_started': self.hide_getting_started,
            'has_setup_feeds': self.has_setup_feeds,
            'has_found_friends': self.has_found_friends,
            'has_trained_intelligence': self.has_trained_intelligence,
            'dashboard_date': self.dashboard_date
        }

    def save(self, *args, **kwargs):
        if not self.secret_token:
            self.secret_token = generate_secret_token(self.user.username, 12)
        try:
            super(Profile, self).save(*args, **kwargs)
        except DatabaseError:
            print " ---> Profile not saved. Table isn't there yet."

    def delete_user(self, confirm=False):
        if not confirm:
            print " ---> You must pass confirm=True to delete this user."
            return

        from apps.social.models import MSocialProfile, MSharedStory, MSocialSubscription
        from apps.social.models import MActivity, MInteraction
        try:
            social_profile = MSocialProfile.objects.get(user_id=self.user.pk)
            print " ---> Unfollowing %s followings and %s followers" % (
                social_profile.following_count, social_profile.follower_count)
            for follow in social_profile.following_user_ids:
                social_profile.unfollow_user(follow)
            for follower in social_profile.follower_user_ids:
                follower_profile = MSocialProfile.objects.get(user_id=follower)
                follower_profile.unfollow_user(self.user.pk)
            social_profile.delete()
        except MSocialProfile.DoesNotExist:
            print " ***> No social profile found. S'ok, moving on."
            pass

        shared_stories = MSharedStory.objects.filter(user_id=self.user.pk)
        print " ---> Deleting %s shared stories" % shared_stories.count()
        for story in shared_stories:
            try:
                original_story = MStory.objects.get(pk=story.story_db_id)
                original_story.sync_redis()
            except MStory.DoesNotExist:
                pass
            story.delete()

        subscriptions = MSocialSubscription.objects.filter(
            subscription_user_id=self.user.pk)
        print " ---> Deleting %s social subscriptions" % subscriptions.count()
        subscriptions.delete()

        interactions = MInteraction.objects.filter(user_id=self.user.pk)
        print " ---> Deleting %s interactions for user." % interactions.count()
        interactions.delete()

        interactions = MInteraction.objects.filter(with_user_id=self.user.pk)
        print " ---> Deleting %s interactions with user." % interactions.count(
        )
        interactions.delete()

        activities = MActivity.objects.filter(user_id=self.user.pk)
        print " ---> Deleting %s activities for user." % activities.count()
        activities.delete()

        activities = MActivity.objects.filter(with_user_id=self.user.pk)
        print " ---> Deleting %s activities with user." % activities.count()
        activities.delete()

        print " ---> Deleting user: %s" % self.user
        self.user.delete()

    def activate_premium(self):
        from apps.profile.tasks import EmailNewPremium
        EmailNewPremium.delay(user_id=self.user.pk)

        self.is_premium = True
        self.save()

        subs = UserSubscription.objects.filter(user=self.user)
        for sub in subs:
            sub.active = True
            try:
                sub.save()
                sub.feed.setup_feed_for_premium_subscribers()
            except IntegrityError, Feed.DoesNotExist:
                pass

        self.queue_new_feeds()

        logging.user(
            self.user,
            "~BY~SK~FW~SBNEW PREMIUM ACCOUNT! WOOHOO!!! ~FR%s subscriptions~SN!"
            % (subs.count()))
예제 #4
0
파일: models.py 프로젝트: melody40/monorepo
class Profile(models.Model):
    name = models.CharField(max_length=100)
    timezone = TimeZoneField()