示例#1
0
def rerun_complete_revivals(debug=False):
    """
    Re-run Revivals with status = COMPLETE to keep users engaged
    """
    t0 = datetime.now()
    total_revival, total_mail = 0, 0
    three_days_ago = timezone.now() - timedelta(days=3)
    for revival in Revival.objects.select_related('service').filter(
            status=COMPLETE, is_active=True):
        try:
            refreshed = Revival.objects.get(pk=revival.id)
            if refreshed.is_running:
                continue
            refreshed.is_running = True
            refreshed.save()
            total_revival += 1
        except Revival.DoesNotExist:
            continue

        try:
            mail_renderer = import_by_path(revival.mail_renderer)
            kwargs = {}
            if revival.get_kwargs:
                get_kwargs = import_by_path(revival.get_kwargs)
                kwargs = get_kwargs(revival)
        except:
            revival.is_running = False
            revival.save()
            logger.error("Error when starting revival %s for %s" %
                         (revival.mail_renderer, revival.service),
                         exc_info=True)
            continue

        service = revival.service
        db = revival.service.database
        add_database(db)
        balance = Balance.objects.using(WALLETS_DB_ALIAS).get(
            service_id=service.id)
        if balance.mail_count == 0:
            revival.is_running = False
            revival.save()
            try:
                notify_for_empty_messaging_credit(service, balance)
            except:
                logger.error(
                    "Failed to notify %s for empty messaging credit." %
                    service,
                    exc_info=True)
            continue
        if 0 < balance.mail_count < LOW_MAIL_LIMIT:
            try:
                notify_for_low_messaging_credit(service, balance)
            except:
                logger.error("Failed to notify %s for low messaging credit." %
                             service,
                             exc_info=True)
        tk = revival.model_name.split('.')
        model = get_model(tk[0], tk[1])
        try:
            obj = model._default_manager.using(db).get(pk=revival.object_id)
        except ObjectDoesNotExist:
            revival.is_running = False
            revival.save()
            continue
        try:
            profile_tag = ProfileTag.objects.using(db).get(
                pk=revival.profile_tag_id)
        except:
            revival.is_running = False
            revival.save()
            continue

        set_counters_many(profile_tag)
        revival_local = Revival.objects.using(db).get(pk=revival.id)

        target_queryset = revival_local.target_set.select_related(
            'member').filter(revived_on__lte=three_days_ago,
                             revival_count__lt=MAX_AUTO_REWARDS)
        if target_queryset.count() == 0:
            revival.is_running = False
            revival.save()
            continue
        revival.run_on = timezone.now()
        revival.status = STARTED
        revival.save()
        connection = mail.get_connection()
        try:
            connection.open()
        except:
            revival.is_running = False
            revival.save()
            logger.error(u"Connexion error", exc_info=True)
            continue

        logger.debug("Running rerun_complete_revivals() %s for %s" %
                     (revival.mail_renderer, revival.service))
        for target in target_queryset.order_by('updated_on')[:MAX_BATCH_SEND]:
            if not debug and balance.mail_count == 0:
                revival.is_running = False
                revival.save()
                try:
                    notify_for_empty_messaging_credit(service, balance)
                except:
                    logger.error(
                        "Failed to notify %s for empty messaging credit." %
                        service,
                        exc_info=True)
                break
            member = target.member
            if debug and not member.is_superuser:
                continue
            if member.language:
                activate(member.language)
            else:
                activate('en')

            if getattr(settings, 'UNIT_TESTING', False):
                sender, subject, html_content = mail_renderer(
                    target, obj, revival, **kwargs)
            else:
                try:
                    sender, subject, html_content = mail_renderer(
                        target, obj, revival, **kwargs)
                except:
                    logger.error(
                        "Could not render mail for member %s, Revival %s, Obj: %s"
                        % (member.email, revival.mail_renderer, str(obj)),
                        exc_info=True)
                    continue

            if not html_content:
                continue
            if debug:
                subject = 'Test remind - ' + subject
            msg = XEmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            msg.type = XEmailObject.REVIVAL
            try:
                with transaction.atomic(using=WALLETS_DB_ALIAS):
                    if not debug:
                        balance.mail_count -= 1
                        balance.save()
                    if msg.send():
                        target.revival_count += 1
                        target.revived_on = t0
                        target.save()
                        total_mail += 1
                        increment_history_field(profile_tag,
                                                'smart_revival_history')
                    else:
                        logger.error("Member %s not notified for Content %s" %
                                     (member.email, str(obj)),
                                     exc_info=True)
            except:
                logger.error("Member %s not notified for Content %s" %
                             (member.email, str(obj)),
                             exc_info=True)

        revival.is_running = False
        revival.progress += 1
        revival.save()

        try:
            connection.close()
        except:
            revival.is_running = False
            revival.save()

    diff = datetime.now() - t0
    logger.debug(
        "rerun_complete_revivals() run %d revivals. %d mails sent in %s" %
        (total_revival, total_mail, diff))
示例#2
0
文件: utils.py 项目: kiranHR/Project1
def invite_member(service, member):
    sender = '%s <no-reply@%s>' % (service.project_name, service.domain)
    config = service.config
    try:
        invitation_message = config.__getattribute__('invitation_message')
    except AttributeError:
        return
    template_name = 'revival/mails/suggest_create_account.html'
    kwargs = get_join_reward_pack_list(service=service)
    join_reward_pack_list = kwargs['reward_pack_list']
    if join_reward_pack_list:
        subject = _("Join us on ikwen and earn free coupons." %
                    service.project_name)
        email_type = XEmailObject.REWARDING
    else:
        subject = _("Join our community on ikwen.")
        email_type = XEmailObject.REVIVAL
    if invitation_message or join_reward_pack_list:
        with transaction.atomic(using=WALLETS_DB_ALIAS):
            from echo.models import Balance
            from echo.utils import LOW_MAIL_LIMIT, notify_for_low_messaging_credit, notify_for_empty_messaging_credit
            balance, update = Balance.objects.using(
                WALLETS_DB_ALIAS).get_or_create(service_id=service.id)
            if 0 < balance.mail_count < LOW_MAIL_LIMIT:
                try:
                    notify_for_low_messaging_credit(service, balance)
                except:
                    logger.error(
                        "Failed to notify %s for low messaging credit." %
                        service,
                        exc_info=True)
            if balance.mail_count == 0 and not getattr(settings,
                                                       'UNIT_TESTING', False):
                try:
                    notify_for_empty_messaging_credit(service, balance)
                except:
                    logger.error(
                        "Failed to notify %s for empty messaging credit." %
                        service,
                        exc_info=True)
                return
        invitation_message = invitation_message.replace(
            '$client', member.first_name)
        extra_context = {
            'member_name': member.first_name,
            'join_reward_pack_list': join_reward_pack_list,
            'invitation_message': invitation_message
        }
        try:
            html_content = get_mail_content(subject,
                                            service=service,
                                            template_name=template_name,
                                            extra_context=extra_context)
            msg = XEmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            msg.type = email_type
            if not getattr(settings, 'UNIT_TESTING', False):
                balance.mail_count -= 1
            balance.save()
            Thread(target=lambda m: m.send(), args=(msg, )).start()
            notice = "%s: Invitation sent message to member after ghost registration attempt" % service.project_name_slug
            logger.error(notice, exc_info=True)
        except:
            notice = "%s: Failed to send invite message to member after ghost registration attempt" % service.project_name_slug
            logger.error(notice, exc_info=True)
示例#3
0
def notify_profiles(debug=False):
    """
    Cron job that revive users by mail. Must be configured
    to run with a settings file having 'umbrella' as default database.
    :return:
    """
    t0 = datetime.now()
    seven_hours_ago = t0 - timedelta(hours=7)
    total_revival, total_mail = 0, 0
    for revival in Revival.objects.select_related('service').exclude(
            status=COMPLETE, is_active=False):
        try:
            refreshed = Revival.objects.get(pk=revival.id)
            if refreshed.is_running:
                continue
            refreshed.is_running = True
            refreshed.save()
            total_revival += 1
        except Revival.DoesNotExist:
            continue

        try:
            mail_renderer = import_by_path(revival.mail_renderer)
            kwargs = {}
            if revival.get_kwargs:
                get_kwargs = import_by_path(revival.get_kwargs)
                kwargs = get_kwargs(revival)
        except:
            revival.is_running = False
            revival.save()
            logger.error("Error when starting revival %s for %s" %
                         (revival.mail_renderer, revival.service),
                         exc_info=True)
            continue

        service = revival.service
        db = service.database
        add_database(db)
        balance = Balance.objects.using(WALLETS_DB_ALIAS).get(
            service_id=service.id)
        if balance.mail_count == 0:
            revival.is_running = False
            revival.save()
            try:
                notify_for_empty_messaging_credit(service, balance)
            except:
                logger.error(
                    "Failed to notify %s for empty messaging credit." %
                    service,
                    exc_info=True)
            continue
        if 0 < balance.mail_count < LOW_MAIL_LIMIT:
            try:
                notify_for_low_messaging_credit(service, balance)
            except:
                logger.error("Failed to notify %s for low messaging credit." %
                             service,
                             exc_info=True)
        tk = revival.model_name.split('.')
        model = get_model(tk[0], tk[1])
        try:
            obj = model._default_manager.using(db).get(pk=revival.object_id)
        except ObjectDoesNotExist:
            revival.is_running = False
            revival.save()
            continue
        try:
            profile_tag = ProfileTag.objects.using(db).get(
                pk=revival.profile_tag_id)
        except:
            revival.is_running = False
            revival.save()
            continue

        if revival.status != PENDING:
            revival.is_running = False
            revival.save()
            continue

        set_counters(profile_tag)
        revival_local = Revival.objects.using(db).get(pk=revival.id)
        if debug:
            member_queryset = Member.objects.using(db).filter(
                is_superuser=True)
        else:
            member_queryset = Member.objects.using(db).filter(
                date_joined__lte=seven_hours_ago)
        total = member_queryset.count()
        chunks = total / 500 + 1
        target_count = 0
        for i in range(chunks):
            start = i * 500
            finish = (i + 1) * 500
            for member in member_queryset.order_by(
                    'date_joined')[start:finish]:
                try:
                    profile = MemberProfile.objects.using(db).get(
                        member=member)
                except MemberProfile.DoesNotExist:
                    ref_tag = ProfileTag.objects.using(db).get(slug=REFERRAL)
                    profile = MemberProfile.objects.using(db).create(
                        member=member, tag_fk_list=[ref_tag.id])
                if revival.profile_tag_id in profile.tag_fk_list:
                    if debug:
                        tag = ProfileTag.objects.using(db).get(
                            pk=revival.profile_tag_id)
                        print "Profiles matching on %s for member %s" % (
                            tag, member)
                    if member.email:
                        Target.objects.using(db).get_or_create(
                            revival=revival_local, member=member)
                        target_count += 1

        if target_count == 0:
            revival.is_running = False
            revival.save()
            continue

        revival.run_on = datetime.now()
        revival.status = STARTED
        revival.total = revival_local.target_set.all().count()
        revival.save()

        connection = mail.get_connection()
        try:
            connection.open()
        except:
            revival.is_running = False
            revival.save()
            logger.error(u"Connexion error", exc_info=True)
            continue

        logger.debug("Running notify_profiles() %s for %s" %
                     (revival.mail_renderer, revival.service))
        for target in revival_local.target_set.select_related('member').filter(
                notified=False)[:MAX_BATCH_SEND]:
            if not debug and balance.mail_count == 0:
                revival.is_running = False
                revival.save()
                try:
                    notify_for_empty_messaging_credit(service, balance)
                except:
                    logger.error(
                        "Failed to notify %s for empty messaging credit." %
                        service,
                        exc_info=True)
                break
            member = target.member
            if member.language:
                activate(member.language)
            else:
                activate('en')

            if getattr(settings, 'UNIT_TESTING', False):
                sender, subject, html_content = mail_renderer(
                    target, obj, revival, **kwargs)
            else:
                try:
                    sender, subject, html_content = mail_renderer(
                        target, obj, revival, **kwargs)
                except:
                    logger.error(
                        "Could not render mail for member %s, Revival %s, Obj: %s"
                        % (member.email, revival.mail_renderer, str(obj)),
                        exc_info=True)
                    continue

            if not html_content:
                continue
            if debug:
                subject = 'Test - ' + subject
            msg = XEmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            msg.type = XEmailObject.REVIVAL
            try:
                with transaction.atomic(using=WALLETS_DB_ALIAS):
                    if not debug:
                        balance.mail_count -= 1
                        balance.save()
                    if msg.send():
                        target.revival_count += 1
                        target.notified = True
                        target.revived_on = t0
                        target.save()
                        total_mail += 1
                        increment_history_field(profile_tag,
                                                'smart_revival_history')
                    else:
                        logger.error("Member %s not notified for Content %s" %
                                     (member.email, str(obj)),
                                     exc_info=True)
            except:
                logger.error("Member %s not notified for Content %s" %
                             (member.email, str(obj)),
                             exc_info=True)
            revival.progress += 1
            revival.save()

        revival.is_running = False
        if revival.progress > 0 and revival.progress >= revival.total:
            revival.status = COMPLETE
        revival.save()

        try:
            connection.close()
        except:
            revival.is_running = False
            revival.save()

    diff = datetime.now() - t0
    logger.debug("notify_profiles() run %d revivals. %d mails sent in %s" %
                 (total_revival, total_mail, diff))
示例#4
0
def notify_profiles(debug=False):
    t0 = datetime.now()
    total_revival, total_mail, total_sms = 0, 0, 0
    logger.debug("Starting cyclic revival")
    today = t0.date()
    queryset = CyclicRevival.objects.select_related('service')\
        .filter(next_run_on=today, hour_of_sending=t0.hour, end_on__gt=today, is_active=True)
    for revival in queryset:
        try:
            refreshed = CyclicRevival.objects.get(pk=revival.id)
            if refreshed.is_running:
                continue
            refreshed.is_running = True
            refreshed.save()
            total_revival += 1
        except CyclicRevival.DoesNotExist:
            continue
        service = revival.service
        db = service.database
        add_database(db)
        balance = Balance.objects.using(WALLETS_DB_ALIAS).get(
            service_id=service.id)
        if balance.mail_count == 0 and balance.sms_count == 0:
            try:
                notify_for_empty_messaging_credit(service, balance)
            except:
                revival.is_running = False
                revival.save()
                logger.error(
                    "Failed to notify %s for empty messaging credit." %
                    service,
                    exc_info=True)
            continue
        if 0 < balance.mail_count < LOW_MAIL_LIMIT or 0 < balance.sms_count < LOW_SMS_LIMIT:
            try:
                notify_for_low_messaging_credit(service, balance)
            except:
                revival.is_running = False
                revival.save()
                logger.error("Failed to notify %s for low messaging credit." %
                             service,
                             exc_info=True)

        label = get_sms_label(service.config)
        notified_empty_mail_credit = False
        notified_empty_sms_credit = False
        if debug:
            member_queryset = Member.objects.using(db).filter(
                is_superuser=True)
        else:
            member_queryset = Member.objects.using(db).all()
        total = member_queryset.count()
        try:
            profile_tag = ProfileTag.objects.using(db).get(
                pk=revival.profile_tag_id)
        except ProfileTag.DoesNotExist:
            revival.delete()
            continue
        set_counters(profile_tag)

        revival_local = CyclicRevival.objects.using(db).get(pk=revival.id)
        chunks = total / 500 + 1
        for i in range(chunks):
            start = i * 500
            finish = (i + 1) * 500
            for member in member_queryset.order_by(
                    'date_joined')[start:finish]:
                try:
                    profile = MemberProfile.objects.using(db).get(
                        member=member)
                except MemberProfile.DoesNotExist:
                    continue
                match = set(profile.tag_fk_list) & {profile_tag.id}
                if len(match) > 0:
                    if member.email:
                        CyclicTarget.objects.using(db).get_or_create(
                            revival=revival_local, member=member)
        revival.set_next_run_date()

        connection = mail.get_connection()
        try:
            connection.open()
        except:
            logger.error(u"Connexion error", exc_info=True)
            break

        logger.debug("Running revival %s for %s" %
                     (revival.mail_subject, revival.service))
        for target in revival_local.cyclictarget_set.select_related('member'):
            member = target.member
            if member.language:
                activate(member.language)
            else:
                activate('en')
            subject = revival.mail_subject
            message = revival.mail_content.replace('$client',
                                                   member.first_name)
            sender = '%s <no-reply@%s>' % (service.project_name,
                                           service.domain)
            try:
                currency = Currency.objects.using(using=db).get(is_base=True)
            except Currency.DoesNotExist:
                currency = None
            product_list = []
            if service.app.slug == 'kakocase':
                product_list = Product.objects.using(db).filter(
                    pk__in=revival.items_fk_list)
            extra_context = {
                'revival':
                revival,
                'currency':
                currency,
                'media_url':
                getattr(settings, 'CLUSTER_MEDIA_URL') +
                service.project_name_slug + '/',
                'product_list':
                product_list
            }
            try:
                html_content = get_mail_content(
                    subject,
                    message,
                    template_name='revival/mails/default.html',
                    service=service,
                    extra_context=extra_context)
            except:
                logger.error(
                    "Could not render mail for member %s, Cyclic revival on %s"
                    % (member.username, profile_tag),
                    exc_info=True)
                break
            msg = XEmailMessage(subject, html_content, sender, [member.email])
            msg.content_subtype = "html"
            msg.type = XEmailObject.REVIVAL

            if balance.mail_count == 0 and not notified_empty_mail_credit:
                notify_for_empty_messaging_credit(service, balance)
                notified_empty_mail_credit = True
            else:
                try:
                    with transaction.atomic(using=WALLETS_DB_ALIAS):
                        if not debug:
                            balance.mail_count -= 1
                            balance.save()
                        if msg.send():
                            target.revival_count += 1
                            target.save()
                            total_mail += 1
                            increment_history_field(
                                profile_tag, 'cyclic_revival_mail_history')
                        else:
                            logger.error(
                                "Cyclic revival with subject %s not sent for member %s"
                                % (subject, member.email),
                                exc_info=True)
                except:
                    logger.error(
                        "Critical error in revival %s when processing Mail sending for member %s"
                        % (revival.id, member.email),
                        exc_info=True)
            if revival.sms_text:
                if balance.sms_count == 0 and not notified_empty_sms_credit:
                    notify_for_empty_messaging_credit(service, balance)
                    notified_empty_sms_credit = True
                else:
                    sms_text = revival.sms_text.replace(
                        '$client', member.first_name)
                    page_count = count_pages(sms_text)
                    try:
                        with transaction.atomic(using=WALLETS_DB_ALIAS):
                            balance.sms_count -= page_count
                            balance.save()
                            send_sms(recipient=member.phone,
                                     text=sms_text,
                                     fail_silently=False)
                            total_sms += 1
                            increment_history_field(
                                profile_tag, 'cyclic_revival_sms_history')
                            SMSObject.objects.create(recipient=member.phone,
                                                     text=sms_text,
                                                     label=label)
                    except:
                        logger.error(
                            "Critical error in revival %s when processing SMS sending for member %s"
                            % (revival.id, member.email),
                            exc_info=True)
            if balance.mail_count == 0 and balance.sms_count == 0:
                break
        revival.is_running = False
        revival.save()
        try:
            connection.close()
        except:
            pass
        diff = datetime.now() - t0
        logger.debug("%d revivals run. %d mails and %d SMS sent in %s" %
                     (total_revival, total_mail, total_sms, diff))