diff --git a/parsons/action_kit/action_kit.py b/parsons/action_kit/action_kit.py index 35b5db3383..0a2680cddf 100644 --- a/parsons/action_kit/action_kit.py +++ b/parsons/action_kit/action_kit.py @@ -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. @@ -232,6 +254,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 @@ -354,6 +424,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 + `_. + 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 + `_ and + `ActionKit's docs on the search API + `_. + + .. 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 + `_. + `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. diff --git a/test/test_action_kit.py b/test/test_action_kit.py index 6a0b3fb454..8b97233e07 100644 --- a/test/test_action_kit.py +++ b/test/test_action_kit.py @@ -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 @@ -110,6 +130,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() @@ -185,6 +238,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)