Files
edx-platform/scripts/user_retirement/utils/thirdparty_apis/hubspot_api.py
Muhammad Farhan Khan 65ea55c8aa Move user retirement scripts code from the tubular repo (#34063)
* refactor: Migragte user retirement scripts code from the tubular repo
2024-02-22 11:09:00 -05:00

124 lines
3.8 KiB
Python

"""
Helper API classes for calling Hubspot APIs.
"""
import logging
import os
import backoff
import requests
from scripts.user_retirement.utils.email_utils import send_email
LOG = logging.getLogger(__name__)
MAX_ATTEMPTS = int(os.environ.get('RETRY_HUBSPOT_MAX_ATTEMPTS', 5))
GET_VID_FROM_EMAIL_URL_TEMPLATE = "https://api.hubapi.com/contacts/v1/contact/email/{email}/profile"
DELETE_USER_FROM_VID_TEMPLATE = "https://api.hubapi.com/contacts/v1/contact/vid/{vid}"
class HubspotException(Exception):
pass
class HubspotAPI:
"""
Hubspot API client used to make calls to Hubspot
"""
def __init__(
self,
hubspot_api_key,
aws_region,
from_address,
alert_email
):
self.api_key = hubspot_api_key
self.aws_region = aws_region
self.from_address = from_address
self.alert_email = alert_email
@backoff.on_exception(
backoff.expo,
HubspotException,
max_tries=MAX_ATTEMPTS
)
def delete_user(self, learner):
"""
Delete a learner from hubspot using their email address.
"""
email = learner.get('original_email', None)
if not email:
raise TypeError('Expected an email address for user to delete, but received None.')
user_vid = self.get_user_vid(email)
if user_vid:
self.delete_user_by_vid(user_vid)
def delete_user_by_vid(self, vid):
"""
Delete a learner from hubspot using their Hubspot `vid` (unique identifier)
"""
headers = {
'content-type': 'application/json',
'authorization': f'Bearer {self.api_key}'
}
req = requests.delete(DELETE_USER_FROM_VID_TEMPLATE.format(
vid=vid
), headers=headers)
error_msg = ""
if req.status_code == 200:
LOG.info("User successfully deleted from Hubspot")
self.send_marketing_alert(vid)
elif req.status_code == 401:
error_msg = "Hubspot user deletion failed due to authorized API call"
elif req.status_code == 404:
error_msg = "Hubspot user deletion failed because vid doesn't match user"
elif req.status_code == 500:
error_msg = "Hubspot user deletion failed due to server-side (Hubspot) issues"
else:
error_msg = "Hubspot user deletion failed due to unknown reasons"
if error_msg:
LOG.error(error_msg)
raise HubspotException(error_msg)
def get_user_vid(self, email):
"""
Get a user's `vid` from Hubspot. `vid` is the terminology that hubspot uses for a user ids
"""
headers = {
'content-type': 'application/json',
'authorization': f'Bearer {self.api_key}'
}
req = requests.get(GET_VID_FROM_EMAIL_URL_TEMPLATE.format(
email=email
), headers=headers)
if req.status_code == 200:
req_data = req.json()
return req_data.get('vid')
elif req.status_code == 404:
LOG.info("No action taken because no user was found in Hubspot.")
return
else:
error_msg = "Error attempted to get user_vid from Hubspot. Error: {}".format(
req.text
)
LOG.error(error_msg)
raise HubspotException(error_msg)
def send_marketing_alert(self, vid):
"""
Notify marketing with user's Hubspot `vid` upon successful deletion.
"""
subject = "Alert: Hubspot Deletion"
body = "Learner with the VID \"{}\" has been deleted from Hubspot.".format(vid)
send_email(
self.aws_region,
self.from_address,
[self.alert_email],
subject,
body
)