import logging from datetime import timedelta from celery import task from django.db.models import Q, F from django.db import transaction from django.conf import settings from django.utils import timezone from django.template.loader import get_template from django.core.mail import send_mass_mail from constance import config as site_config import django_lcore from ccvpn.common import parse_integer_list from lambdainst.models import User, VPNUser ROOT_URL = settings.ROOT_URL SITE_NAME = settings.TICKETS_SITE_NAME logger = logging.getLogger(__name__) @task(autoretry_for=(Exception,), default_retry_delay=60*60) def push_all_users(): for u in User.objects.all(): # skip 'empty' accounts if u.vpnuser.expiration is None: continue logger.debug("pushing user %r", u) django_lcore.sync_user(u.vpnuser, fail_silently=False) @task(autoretry_for=(Exception,), max_retries=10, retry_backoff=True) def push_user(user_id): user = User.objects.get(id=user_id) logger.debug("pushing user %r", user) django_lcore.sync_user(user.vpnuser, fail_silently=False) @task def notify_account_expiration(): """ Notify users near the end of their subscription """ from_email = settings.DEFAULT_FROM_EMAIL for v in parse_integer_list(site_config.NOTIFY_DAYS_BEFORE): emails = [] users = list(get_next_expirations(v)) logging.info("sending -%d day notification to %d users", v, len(users)) with transaction.atomic(): for u in users: # Ignore users with active subscriptions # They will get notified only if it gets cancelled (payments # processors will cancel after a few failed payments) if u.get_subscription(): continue ctx = dict(site_name=SITE_NAME, user=u.user, exp=u.expiration, url=ROOT_URL) text = get_template('lambdainst/mail_expire_soon.txt').render(ctx) emails.append(("CCrypto VPN Expiration", text, from_email, [u.user.email])) logging.debug("sending -%d days notify to %s" % (v, u.user.email)) u.last_expiry_notice = timezone.now() u.save() send_mass_mail(emails) def get_next_expirations(days=3): """ Gets users whose subscription will expire in some days """ limit_date = timezone.now() + timedelta(days=days) users = VPNUser.objects.exclude(user__email__exact='') users = users.filter(expiration__gt=timezone.now()) # Not expired users = users.filter(expiration__lt=limit_date) # Expire in a few days # Make sure we dont send the notice twice users = users.filter(Q(last_expiry_notice__isnull=True) | Q(expiration__gt=F('last_expiry_notice') + timedelta(days=days))) return users