text: # -*- coding: utf-8 -*-
  
  from django.db import transaction
  import mailchimp
  
  from framework import sentry
  from framework.celery_tasks import app
  from framework.celery_tasks.handlers import queued_task
  from framework.auth.signals import user_confirmed
  from osf.models import OSFUser
  from website import settings
  
  
  def get_mailchimp_api():
      if not settings.MAILCHIMP_API_KEY:
          raise mailchimp.InvalidApiKeyError(
              'An API key is required to connect to Mailchimp.'
          )
      return mailchimp.Mailchimp(settings.MAILCHIMP_API_KEY)
  
  
  def get_list_id_from_name(list_name):
      m = get_mailchimp_api()
      mailing_list = m.lists.list(filters={'list_name': list_name})
      return mailing_list['data'][0]['id']
  
  
  def get_list_name_from_id(list_id):
      m = get_mailchimp_api()
      mailing_list = m.lists.list(filters={'list_id': list_id})
      return mailing_list['data'][0]['name']
  
  
  @queued_task
  @app.task
  @transaction.atomic
  def subscribe_mailchimp(list_name, user_id):
      user = OSFUser.load(user_id)
      m = get_mailchimp_api()
      list_id = get_list_id_from_name(list_name=list_name)
  
      if user.mailchimp_mailing_lists is None:
          user.mailchimp_mailing_lists = {}
  
      try:
          m.lists.subscribe(
              id=list_id,
              email={'email': user.username},
              merge_vars={
                  'fname': user.given_name,
                  'lname': user.family_name,
              },
              double_optin=False,
              update_existing=True,
          )
  
      except (mailchimp.ValidationError, mailchimp.ListInvalidBounceMemberError) as error:
          sentry.log_exception()
          sentry.log_message(error.message)
          user.mailchimp_mailing_lists[list_name] = False
      else:
          user.mailchimp_mailing_lists[list_name] = True
      finally:
          user.save()
  
  
  def unsubscribe_mailchimp(list_name, user_id, username=None, send_goodbye=True):
      """Unsubscribe a user from a mailchimp mailing list given its name.
  
      :param str list_name: mailchimp mailing list name
      :param str user_id: current user's id
      :param str username: current user's email (required for merged users)
  
      :raises: ListNotSubscribed if user not already subscribed
      """
      user = OSFUser.load(user_id)
      m = get_mailchimp_api()
      list_id = get_list_id_from_name(list_name=list_name)
      m.lists.unsubscribe(id=list_id, email={'email': username or user.username}, send_goodbye=send_goodbye)
  
      # Update mailing_list user field
      if user.mailchimp_mailing_lists is None:
          user.mailchimp_mailing_lists = {}
          user.save()
  
      user.mailchimp_mailing_lists[list_name] = False
      user.save()
  
  @queued_task
  @app.task
  @transaction.atomic
  def unsubscribe_mailchimp_async(list_name, user_id, username=None, send_goodbye=True):
      """ Same args as unsubscribe_mailchimp, used to have the task be run asynchronously
      """
      unsubscribe_mailchimp(list_name=list_name, user_id=user_id, username=username, send_goodbye=send_goodbye)
  
  @user_confirmed.connect
  def subscribe_on_confirm(user):
      # Subscribe user to general OSF mailing list upon account confirmation
      if settings.ENABLE_EMAIL_SUBSCRIPTIONS:
          subscribe_mailchimp(settings.MAILCHIMP_GENERAL_LIST, user._id)
  