Skip to content

Commit

Permalink
Merge pull request #2141 from Sefaria/feature/sc-30355/update-api-sub…
Browse files Browse the repository at this point in the history
…scribe-endpoint-for-multiple

Update subscribe endpoint for multiple newsletter subscriptions
  • Loading branch information
nsantacruz authored Dec 24, 2024
2 parents ffdf7e8 + a676872 commit 59e71f8
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
7 changes: 5 additions & 2 deletions sefaria/helper/crm/crm_mediator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ def create_crm_user(self, email, first_name, last_name, lang="en", educator=Fals
except:
return False

def subscribe_to_lists(self, email, first_name, last_name, educator=False, lang="en"):
return self._crm_connection.subscribe_to_lists(email, first_name, last_name, educator, lang)
def subscribe_to_lists(self, email, first_name, last_name, educator=False, lang="en", mailing_lists=None):
return self._crm_connection.subscribe_to_lists(email, first_name, last_name, educator, lang, mailing_lists)

def sync_sustainers(self):
current_sustainers = CrmInfoStore.get_current_sustainers()
Expand Down Expand Up @@ -71,3 +71,6 @@ def get_and_save_crm_id(self, email=None):
CrmInfoStore.save_crm_id(crm_id, email)
else:
return False

def get_available_lists(self):
return self._crm_connection.get_available_lists()
33 changes: 29 additions & 4 deletions sefaria/helper/crm/salesforce.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
from sefaria.helper.crm.crm_connection_manager import CrmConnectionManager
from sefaria import settings as sls

from typing import Any, Optional

class SalesforceNewsletterListRetrievalError(Exception):
pass

class SalesforceConnectionManager(CrmConnectionManager):
def __init__(self):
CrmConnectionManager.__init__(self, sls.SALESFORCE_BASE_URL)
Expand All @@ -25,7 +30,7 @@ def make_request(self, request, **kwargs):

def get(self, endpoint):
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
return self.session.get(endpoint, headers)
return self.session.get(endpoint, headers=headers)

def post(self, endpoint, **kwargs):
headers = {'Content-type': 'application/json', 'Accept': 'application/json'}
Expand Down Expand Up @@ -120,8 +125,17 @@ def find_crm_id(self, email=None):
except:
return False

def subscribe_to_lists(self, email, first_name=None, last_name=None, lang="en", educator=False):
# TODO: Implement once endpoint exists
def subscribe_to_lists(
self,
email: str,
first_name: Optional[str] = None,
last_name: Optional[str] = None,
lang: str = "en",
educator: bool = False,
mailing_lists: Optional[list[str]] = None) -> Any:

mailing_lists = mailing_lists or []

CrmConnectionManager.subscribe_to_lists(self, email, first_name, last_name, lang, educator)
if lang == "he":
language = "Hebrew"
Expand All @@ -134,7 +148,8 @@ def subscribe_to_lists(self, email, first_name=None, last_name=None, lang="en",
"Last_Name__c": last_name,
"Sefaria_App_Email__c": email,
"Hebrew_English__c": language,
"Educator__c": educator
"Educator__c": educator,
"Newsletter_Names__c": mailing_lists
})
res = self.post(self.create_endpoint("Sefaria_App_Data__c"),
json={
Expand All @@ -145,3 +160,13 @@ def subscribe_to_lists(self, email, first_name=None, last_name=None, lang="en",
except:
return False
return res

def get_available_lists(self) -> list[str]:
try:
resource_prefix = f"services/data/v{self.version}/query"
endpoint = f"{sls.SALESFORCE_BASE_URL}/{resource_prefix}/"
response = self.get(endpoint + "?q=SELECT+Subscriptions__c+FROM+AC_to_SF_List_Mapping__mdt")
records = response.json()["records"]
return [record["Subscriptions__c"] for record in records]
except (requests.RequestException, KeyError, json.JSONDecodeError, AttributeError):
raise SalesforceNewsletterListRetrievalError("Unable to retrieve newsletter mailing lists from Salesforce CRM")
3 changes: 2 additions & 1 deletion sefaria/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,10 +398,11 @@
url(r'^api/send_feedback$', sefaria_views.generate_feedback),
]

# Email Subscribe
# Email Newsletter Subscriptions
urlpatterns += [
url(r'^api/subscribe/(?P<org>.+)/(?P<email>.+)$', sefaria_views.generic_subscribe_to_newsletter_api),
url(r'^api/subscribe/(?P<email>.+)$', sefaria_views.subscribe_sefaria_newsletter_view),
url(r'^api/newsletter_mailing_lists/?$', sefaria_views.get_available_newsletter_mailing_lists),
]

# Admin
Expand Down
20 changes: 16 additions & 4 deletions sefaria/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import sefaria.model as model
import sefaria.system.cache as scache
from sefaria.helper.crm.crm_mediator import CrmMediator
from sefaria.helper.crm.salesforce import SalesforceNewsletterListRetrievalError
from sefaria.system.cache import in_memory_cache
from sefaria.client.util import jsonResponse, send_email, read_webpack_bundle
from sefaria.forms import SefariaNewUserForm, SefariaNewUserFormAPI, SefariaDeleteUserForm, SefariaDeleteSheet
Expand Down Expand Up @@ -204,16 +205,27 @@ def subscribe_sefaria_newsletter_view(request, email):

def subscribe_sefaria_newsletter(request, email, first_name, last_name):
"""
API for subscribing to mailing lists, in `lists` url param.
Currently active lists are:
"Announcements_General", "Announcements_General_Hebrew", "Announcements_Edu", "Announcements_Edu_Hebrew"
API for subscribing to mailing lists
* By default, the user's email address is subscribed to the default lists: "Master," "General Updates" (or the one for Hebrew), and "Educator Updates" (if the user is an educator).
* If the user's email address already exists, the email address to those lists is not resubscribed to those lists
* When you provide additional newsletter mailing lists, the email address will be subscribed to those lists, along with the default ones, if the email address does not already exist.
* However, if we pass the email address with any of those default newsletter lists as additional ones, Salesforce will resubscribe the email address to those lists.
"""
body = json.loads(request.body)
language = body.get("language", "")
educator = body.get("educator", False)
mailing_lists = body.get("lists", [])
crm_mediator = CrmMediator()
return crm_mediator.subscribe_to_lists(email, first_name, last_name, educator=educator, lang=language)
return crm_mediator.subscribe_to_lists(email, first_name, last_name, educator=educator, lang=language, mailing_lists=mailing_lists)

@csrf_exempt
def get_available_newsletter_mailing_lists(request):
try:
return jsonResponse({"newsletter_mailing_lists": CrmMediator().get_available_lists()})
except SalesforceNewsletterListRetrievalError as e:
return jsonResponse({"error": str(e)}, status=502)
except:
return jsonResponse({"error": "Unknown error occurred"}, status=500)

def subscribe_steinsaltz(request, email, first_name, last_name):
"""
Expand Down

0 comments on commit 59e71f8

Please sign in to comment.