Commit 07ffcfd7 by Ahsan Ulhaq Committed by GitHub

Merge pull request #14033 from edx/ahsan/ECOM-6324

WL Enrollees on edX.org email list
parents 5d4514d7 eb895fae
"""
This module contains signals needed for email integration
"""
import logging
import datetime
import crum
import datetime
import logging
from django.dispatch import receiver
from django.core.urlresolvers import reverse
from django.conf import settings
from django.core.urlresolvers import reverse
from django.dispatch import receiver
from student.models import ENROLL_STATUS_CHANGE
from student.cookies import CREATE_LOGON_COOKIE
from student.views import REGISTER_USER
from email_marketing.models import EmailMarketingConfiguration
from util.model_utils import USER_FIELD_CHANGED
from lms.djangoapps.email_marketing.tasks import update_user, update_user_email, update_course_enrollment
from lms.djangoapps.email_marketing.tasks import (
update_user, update_user_email, update_course_enrollment
)
from sailthru.sailthru_client import SailthruClient
from sailthru.sailthru_error import SailthruClientError
......@@ -151,7 +153,9 @@ def email_marketing_register_user(sender, user=None, profile=None,
return
# perform update asynchronously
update_user.delay(_create_sailthru_user_vars(user, user.profile), user.email, new_user=True)
update_user.delay(
_create_sailthru_user_vars(user, user.profile), user.email, site=_get_current_site(), new_user=True
)
@receiver(USER_FIELD_CHANGED)
......@@ -187,10 +191,10 @@ def email_marketing_user_field_changed(sender, user=None, table=None, setting=No
email_config = EmailMarketingConfiguration.current()
if not email_config.enabled:
return
# perform update asynchronously, flag if activation
update_user.delay(_create_sailthru_user_vars(user, user.profile), user.email,
new_user=False,
activation=(setting == 'is_active') and new_value is True)
update_user.delay(_create_sailthru_user_vars(user, user.profile), user.email, site=_get_current_site(),
new_user=False, activation=(setting == 'is_active') and new_value is True)
elif setting == 'email':
# email update is special case
......@@ -218,3 +222,14 @@ def _create_sailthru_user_vars(user, profile):
sailthru_vars['country'] = unicode(profile.country.code)
return sailthru_vars
def _get_current_site():
"""
Returns the site for the current request if any.
"""
request = crum.get_current_request()
if not request:
return
return {'id': request.site.id, 'domain': request.site.domain, 'name': request.site.name}
......@@ -6,6 +6,7 @@ import time
from celery import task
from django.core.cache import cache
from django.conf import settings
from email_marketing.models import EmailMarketingConfiguration
from student.models import EnrollStatusChange
......@@ -14,11 +15,12 @@ from sailthru.sailthru_client import SailthruClient
from sailthru.sailthru_error import SailthruClientError
log = logging.getLogger(__name__)
SAILTHRU_LIST_CACHE_KEY = "email.marketing.cache"
# pylint: disable=not-callable
@task(bind=True, default_retry_delay=3600, max_retries=24)
def update_user(self, sailthru_vars, email, new_user=False, activation=False):
def update_user(self, sailthru_vars, email, site=None, new_user=False, activation=False):
"""
Adds/updates Sailthru profile information for a user.
Args:
......@@ -36,8 +38,9 @@ def update_user(self, sailthru_vars, email, new_user=False, activation=False):
sailthru_client = SailthruClient(email_config.sailthru_key, email_config.sailthru_secret)
try:
sailthru_response = sailthru_client.api_post("user",
_create_sailthru_user_parm(sailthru_vars, email,
new_user, email_config))
_create_email_user_param(sailthru_vars, sailthru_client,
email, new_user, email_config,
site=site))
except SailthruClientError as exc:
log.error("Exception attempting to add/update user %s in Sailthru - %s", email, unicode(exc))
......@@ -111,7 +114,7 @@ def update_user_email(self, new_email, old_email):
max_retries=email_config.sailthru_max_retries)
def _create_sailthru_user_parm(sailthru_vars, email, new_user, email_config):
def _create_email_user_param(sailthru_vars, sailthru_client, email, new_user, email_config, site=None):
"""
Create sailthru user create/update parms
"""
......@@ -119,8 +122,11 @@ def _create_sailthru_user_parm(sailthru_vars, email, new_user, email_config):
sailthru_user['vars'] = dict(sailthru_vars, last_changed_time=int(time.time()))
# if new user add to list
if new_user and email_config.sailthru_new_user_list:
sailthru_user['lists'] = {email_config.sailthru_new_user_list: 1}
if new_user:
list_name = _get_or_create_user_list_for_site(
sailthru_client, site=site, default_list_name=email_config.sailthru_new_user_list
)
sailthru_user['lists'] = {list_name: 1} if list_name else {email_config.sailthru_new_user_list: 1}
return sailthru_user
......@@ -294,6 +300,99 @@ def _get_course_content(course_url, sailthru_client, email_config):
return response
def _get_or_create_user_list_for_site(sailthru_client, site=None, default_list_name=None):
"""
Get the user list name from cache if exists else create one and return the name,
callers of this function should perform the enabled check of email config.
:param: sailthru_client
:param: site
:param: default_list_name
:return: list name if exists or created else return None
"""
if site and site.get('id') != settings.SITE_ID:
list_name = site.get('domain', '').replace(".", "_") + "_user_list"
else:
list_name = default_list_name
sailthru_list = _get_or_create_user_list(sailthru_client, list_name)
return list_name if sailthru_list else default_list_name
def _get_or_create_user_list(sailthru_client, list_name):
"""
Get list from sailthru and return if list_name exists else create a new one
and return list data for all lists.
:param sailthru_client
:param list_name
:return sailthru list
"""
sailthru_list_cache = cache.get(SAILTHRU_LIST_CACHE_KEY)
is_cache_updated = False
if not sailthru_list_cache:
sailthru_list_cache = _get_list_from_email_marketing_provider(sailthru_client)
is_cache_updated = True
sailthru_list = sailthru_list_cache.get(list_name)
if not sailthru_list:
is_created = _create_user_list(sailthru_client, list_name)
if is_created:
sailthru_list_cache = _get_list_from_email_marketing_provider(sailthru_client)
is_cache_updated = True
sailthru_list = sailthru_list_cache.get(list_name)
if is_cache_updated:
cache.set(SAILTHRU_LIST_CACHE_KEY, sailthru_list_cache)
return sailthru_list
def _get_list_from_email_marketing_provider(sailthru_client):
"""
Get sailthru list
:param sailthru_client
:return dict of sailthru lists mapped by list name
"""
try:
sailthru_get_response = sailthru_client.api_get("list", {})
except SailthruClientError as exc:
log.error("Exception attempting to get list from Sailthru - %s", unicode(exc))
return {}
if not sailthru_get_response.is_ok():
error = sailthru_get_response.get_error()
log.info("Error attempting to read list record from Sailthru: %s", error.get_message())
return {}
list_map = dict()
for user_list in sailthru_get_response.json['lists']:
list_map[user_list.get('name')] = user_list
return list_map
def _create_user_list(sailthru_client, list_name):
"""
Create list in Sailthru
:param sailthru_client
:param list_name
:return boolean
"""
list_params = {'list': list_name, 'primary': 0, 'public_name': list_name}
try:
sailthru_response = sailthru_client.api_post("list", list_params)
except SailthruClientError as exc:
log.error("Exception attempting to list record for key %s in Sailthru - %s", list_name, unicode(exc))
return False
if not sailthru_response.is_ok():
error = sailthru_response.get_error()
log.error("Error attempting to create list in Sailthru: %s", error.get_message())
return False
return True
def _update_unenrolled_list(sailthru_client, email, course_url, unenroll):
"""
Maintain a list of courses the user has unenrolled from in the Sailthru user record
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment