Update MembershipWorks module to v2 of the API, where available
still stuck using the v1 csv endpoint, haven't found an easy alternative and it hasn't been changed yet for their v2
This commit is contained in:
parent
cfccc433dd
commit
3849aca918
@ -3,7 +3,7 @@ from io import StringIO
|
||||
|
||||
import requests
|
||||
|
||||
BASE_URL = "https://api.membershipworks.com/v1/"
|
||||
BASE_URL = "https://api.membershipworks.com"
|
||||
|
||||
# extracted from `SF._is.crm` in https://cdn.membershipworks.com/all.js
|
||||
CRM = {
|
||||
@ -72,21 +72,30 @@ class MembershipWorksRemoteError(Exception):
|
||||
|
||||
class MembershipWorks:
|
||||
def __init__(self):
|
||||
self.sess = requests.Session()
|
||||
self.org_info = None
|
||||
self.auth_token = None
|
||||
self.org_num = None
|
||||
|
||||
def login(self, username, password):
|
||||
"""Authenticate against the membershipworks api"""
|
||||
r = requests.post(
|
||||
BASE_URL + "usr",
|
||||
data={"_st": "all", "eml": username, "org": "10000", "pwd": password},
|
||||
r = self.sess.post(
|
||||
BASE_URL + "/v2/account/session",
|
||||
data={"eml": username, "pwd": password},
|
||||
headers={"X-Org": "10000"},
|
||||
)
|
||||
if r.status_code != 200 or "SF" not in r.json():
|
||||
raise MembershipWorksRemoteError("login", r)
|
||||
self.org_info = r.json()
|
||||
self.auth_token = self.org_info["SF"]
|
||||
self.org_num = self.org_info["org"]
|
||||
self.sess.headers.update(
|
||||
{
|
||||
"X-Org": str(self.org_num),
|
||||
"X-Role": "admin",
|
||||
"Authorization": "Bearer " + self.auth_token,
|
||||
}
|
||||
)
|
||||
|
||||
def _inject_auth(self, kwargs):
|
||||
# TODO: should probably be a decorator or something
|
||||
@ -97,12 +106,12 @@ class MembershipWorks:
|
||||
kwargs["params"] = {}
|
||||
kwargs["params"]["SF"] = self.auth_token
|
||||
|
||||
def _get(self, *args, **kwargs):
|
||||
def _get_v1(self, *args, **kwargs):
|
||||
self._inject_auth(kwargs)
|
||||
# TODO: should probably do some error handling in here
|
||||
return requests.get(*args, **kwargs)
|
||||
|
||||
def _post(self, *args, **kwargs):
|
||||
def _post_v1(self, *args, **kwargs):
|
||||
self._inject_auth(kwargs)
|
||||
# TODO: should probably do some error handling in here
|
||||
return requests.post(*args, **kwargs)
|
||||
@ -141,32 +150,30 @@ class MembershipWorks:
|
||||
for dek in self.org_info["dek"]:
|
||||
# TODO: there must be a better way. this is stupid
|
||||
if dek["dek"] == 1:
|
||||
ret["folders"][dek["lbl"]] = dek["_id"]
|
||||
ret["folders"][dek["lbl"]] = dek["did"]
|
||||
elif "cur" in dek:
|
||||
ret["levels"][dek["lbl"]] = dek["_id"]
|
||||
ret["levels"][dek["lbl"]] = dek["did"]
|
||||
elif "mux" in dek:
|
||||
ret["addons"][dek["lbl"]] = dek["_id"]
|
||||
ret["addons"][dek["lbl"]] = dek["did"]
|
||||
else:
|
||||
ret["labels"][dek["lbl"]] = dek["_id"]
|
||||
ret["labels"][dek["lbl"]] = dek["did"]
|
||||
|
||||
return ret
|
||||
|
||||
def get_member_ids(self, folders):
|
||||
folder_map = self._parse_flags()["folders"]
|
||||
|
||||
r = self._get(
|
||||
BASE_URL + "ylp",
|
||||
params={
|
||||
"lbl": ",".join([folder_map[f] for f in folders]),
|
||||
"org": self.org_num,
|
||||
"var": "_id,nam,ctc",
|
||||
},
|
||||
r = self.sess.get(
|
||||
BASE_URL + "/v2/accounts",
|
||||
params={"dek": ",".join([folder_map[f] for f in folders])},
|
||||
)
|
||||
if r.status_code != 200 or "usr" not in r.json():
|
||||
raise MembershipWorksRemoteError("user listing", r)
|
||||
|
||||
# get list of member ID matching the search
|
||||
return [user["uid"] for user in r.json()["usr"]]
|
||||
# dedup with set() to work around people with alt uids
|
||||
# TODO: figure out why people have alt uids
|
||||
return set(user["uid"] for user in r.json()["usr"])
|
||||
|
||||
# TODO: has issues with aliasing header names:
|
||||
# ex: "Personal Studio Space" Label vs Membership Addon/Field
|
||||
@ -179,8 +186,8 @@ class MembershipWorks:
|
||||
|
||||
# get members CSV
|
||||
# TODO: maybe can just use previous get instead? would return JSON
|
||||
r = self._post(
|
||||
BASE_URL + "csv",
|
||||
r = self._post_v1(
|
||||
BASE_URL + "/v1/csv",
|
||||
data={
|
||||
"_rt": "946702800", # unknown
|
||||
"mux": "", # unknown
|
||||
@ -200,8 +207,8 @@ class MembershipWorks:
|
||||
json gets a different version of the transactions list,
|
||||
which contains a different set information
|
||||
"""
|
||||
r = self._get(
|
||||
BASE_URL + "csv",
|
||||
r = self._get_v1(
|
||||
BASE_URL + "/v1/csv",
|
||||
params={
|
||||
"crm": "12,13,14,18,19", # transaction types, see CRM
|
||||
**({"txl": ""} if json else {}),
|
||||
|
Reference in New Issue
Block a user