Skip to content

Commit

Permalink
Add methods to add a phone number, create and update event fields, an…
Browse files Browse the repository at this point in the history
…d search events in a campaign. (#1076)
  • Loading branch information
strangeways authored Jun 18, 2024
1 parent 3ff0eac commit 606dfbc
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 0 deletions.
137 changes: 137 additions & 0 deletions parsons/action_kit/action_kit.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,28 @@ def create_user(self, email, **kwargs):
**kwargs,
)

def add_phone(self, user_id, phone_type, phone):
"""
Add a phone number to a user.
`Args:`
user_id: string
The id of the user.
phone_type: string
The type of the phone (e.g., "Home").
phone: string
The phone number.
`Returns:`
Phone json object
"""
return self._base_post(
endpoint="phone",
exception_message="Could not create phone",
user=f"/rest/v1/user/{user_id}/",
phone_type=phone_type,
phone=phone,
)

def delete_actionfield(self, actionfield_id):
"""
Delete an actionfield.
Expand Down Expand Up @@ -251,6 +273,54 @@ def update_event(self, event_id, **kwargs):
resp = self.conn.patch(self._base_endpoint("event", event_id), data=json.dumps(kwargs))
logger.info(f"{resp.status_code}: {event_id}")

def create_event_field(self, event_id, name, value):
"""
Create an event field (custom field on an event). Note that if an event
field with this name already exists, this will add a second record.
`Args:`
event_id: int
The id for the event.
name: string
The name of the event field.
value: string
The value of the event field.
`Returns:`
Event field json object
"""
return self._base_post(
endpoint="eventfield",
exception_message="Could not create event field",
event=f"/rest/v1/event/{event_id}/",
name=name,
value=value,
)

def update_event_field(self, eventfield_id, name, value):
"""
Update an event field.
`Args:`
eventfield_id: int
The id of the event field to update.
name: string
The name of the event field.
value: string
The value of the event field.
`Returns:`
``None``
"""
resp = self.conn.patch(
self._base_endpoint("eventfield", eventfield_id),
data=json.dumps(
{
"name": name,
"value": value,
}
),
)
logger.info(f"{resp.status_code}: {eventfield_id}")

def get_blackholed_email(self, email):
"""
Get a blackholed email. A blackholed email is an email that has been prevented from
Expand Down Expand Up @@ -373,6 +443,73 @@ def create_campaign(self, name, **kwargs):
**kwargs,
)

def search_events_in_campaign(
self,
campaign_id,
limit=None,
order_by="id",
ascdesc="asc",
filters=None,
exclude=None,
**kwargs,
):
"""
Get events in a campaign, with optional search filters.
`Args:`
campaign_id: int
The id of the event campaign.
limit: int
The maximum number of objects to return.
order_by: string
Event attribute to order the results by. Defaults to id, which will normally
be equivalent to ordering by created_at. See `ActionKit's docs on ordering
<https://roboticdogs.actionkit.com/docs//manual/api/rest/overview.html#ordering>`_.
ascdesc: string
If "asc" (the default), returns events ordered by the attribute specified by
the order_by parameter. If "desc", returns events in reverse order.
filters: dictionary
A dictionary for filtering by the attributes of the event or related object.
Not all attributes are available for filtering, but an eventfield will work.
For additional info, visit `Django's docs on field lookups
<https://docs.djangoproject.com/en/3.1/topics/db/queries/#field-lookups>`_ and
`ActionKit's docs on the search API
<https://roboticdogs.actionkit.com/docs/manual/api/rest/examples/eventsearch.html>`_.
.. code-block:: python
{
"title": "Example Event Title",
"field__name": "example_event_field_name",
"field__value": "Example event field value",
}
exclude: dictionary
A dictionary for excluding by the attributes of the event or related object.
Uses the same format as the filters argument.
**kwargs:
A dictionary of other options for filtering. See `ActionKit's docs on the
search API
<https://roboticdogs.actionkit.com/docs/manual/api/rest/examples/eventsearch.html>`_.
`Returns:`
Parsons.Table
The list of events.
"""
if filters:
for field, value in filters.items():
kwargs[f"filter[{field}]"] = value
if exclude:
for field, value in exclude.items():
kwargs[f"exclude[{field}]"] = value
if ascdesc == "asc":
kwargs["order_by"] = order_by
else:
kwargs["order_by"] = f"-{order_by}"
return self.paginated_get(
f"campaign/{campaign_id}/event_search",
limit=limit,
**kwargs,
)

def get_event_create_page(self, event_create_page_id):
"""
Get a event create page.
Expand Down
86 changes: 86 additions & 0 deletions test/test_action_kit.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,26 @@ def test_create_user(self):
data=json.dumps({"email": "test"}),
)

def test_add_phone(self):
# Test add phone

# Mock resp and status code
resp_mock = mock.MagicMock()
type(resp_mock.post()).status_code = mock.PropertyMock(return_value=201)
self.actionkit.conn = resp_mock

self.actionkit.add_phone(user_id=123, phone_type="home", phone="+12025550101")
self.actionkit.conn.post.assert_called_with(
"https://domain.actionkit.com/rest/v1/phone/",
data=json.dumps(
{
"user": "/rest/v1/user/123/",
"phone_type": "home",
"phone": "+12025550101",
}
),
)

def test_update_user(self):
# Test update user

Expand Down Expand Up @@ -126,6 +146,39 @@ def test_update_event(self):
data=json.dumps({"is_approved": "test"}),
)

def test_create_event_field(self):
# Test create event field

# Mock resp and status code
resp_mock = mock.MagicMock()
type(resp_mock.post()).status_code = mock.PropertyMock(return_value=201)
self.actionkit.conn = resp_mock

self.actionkit.create_event_field(event_id=123, name="name", value="value")
self.actionkit.conn.post.assert_called_with(
"https://domain.actionkit.com/rest/v1/eventfield/",
data=json.dumps(
{
"event": "/rest/v1/event/123/",
"name": "name",
"value": "value",
}
),
)

def test_update_event_field(self):
# Test update event field

# Mock resp and status code
resp_mock = mock.MagicMock()
type(resp_mock.patch()).status_code = mock.PropertyMock(return_value=202)
self.actionkit.conn = resp_mock
self.actionkit.update_event_field(456, name="name", value="value")
self.actionkit.conn.patch.assert_called_with(
"https://domain.actionkit.com/rest/v1/eventfield/456/",
data=json.dumps({"name": "name", "value": "value"}),
)

def test_get_blackholed_email(self):
# Test get blackholed email
resp_mock = mock.MagicMock()
Expand Down Expand Up @@ -201,6 +254,39 @@ def test_create_campaign(self):
data=json.dumps({"name": "new_campaign", "field": "field"}),
)

def test_search_events_in_campaign(self):
# Test search events in campaign
resp_mock = mock.MagicMock()
type(resp_mock.get()).status_code = mock.PropertyMock(return_value=201)
type(resp_mock.get()).json = lambda x: {"meta": {"next": ""}, "objects": []}
self.actionkit.conn = resp_mock

self.actionkit.search_events_in_campaign(
123,
limit=100,
order_by="created_at",
ascdesc="desc",
filters={
"title": "Event Title",
"field__name": "event_field_name",
"field__value": "Event field value",
},
exclude={
"creator__email": "host@example.com",
},
)
self.actionkit.conn.get.assert_called_with(
"https://domain.actionkit.com/rest/v1/campaign/123/event_search/",
params={
"filter[title]": "Event Title",
"filter[field__name]": "event_field_name",
"filter[field__value]": "Event field value",
"exclude[creator__email]": "host@example.com",
"order_by": "-created_at",
"_limit": 100,
},
)

def test_get_event(self):
# Test get event
self.actionkit.get_event(1)
Expand Down

0 comments on commit 606dfbc

Please sign in to comment.