Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
dist
build
MANIFEST
.DS_Store
36 changes: 36 additions & 0 deletions hapi/contacts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from hapi_plus.base import BaseClient
from urllib import quote

CONTACTS_API_VERSION = '1'


class ContactsClient(BaseClient):

def _get_path(self, subpath):
return 'contacts/v%s/%s' % (CONTACTS_API_VERSION, subpath)

def get_contact(self, contact_id, **options):
return self._call('contact/vid/%s/profile' % contact_id, **options)

def get_contact_by_email(self, email, **options):
return self._call('contact/email/%s/profile' % quote(email), **options)

def create_contact(self, data, **options):
return self._call('contact/', data=data, method='POST', **options)

def update_contact(self, contact_id, data, **options):
return self._call('contact/vid/%s/profile' % contact_id, data=data, method='POST', **options)

def archive_contact(self, contact_id, **options):
return self._call('contact/vid/%s' % contact_id, method='DELETE', **options)

def get_statistics(self, **options):
return self._call('contacts/statistics', **options)

def search(self, query, properties=None, **options):
params = {'q': query}

if properties:
params['property'] = properties

return self._call('search/query', params, doseq=True, **options)
38 changes: 38 additions & 0 deletions hapi/groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from hapi_plus.base import BaseClient
import unicodedata
import re

GROUPS_API_VERSION = '1'


class GroupsClient(BaseClient):

def _get_path(self, subpath):
return 'contacts/v%s/%s' % (GROUPS_API_VERSION, subpath)

def get_groups(self, **options):
return self._call('groups', **options)

def get_group(self, group_name, **options):
valid_name = validate_name(group_name)
return self._call('groups/%s' % valid_name, **options)

def create_group(self, group_name,data, **options):
valid_name = validate_name(group_name)
return self._call('groups/%s' % valid_name, data=data, method='PUT', **options)

def update_group(self, group_name, data, **options):
valid_name = validate_name(group_name)
return self._call('groups/%s' % valid_name, data=data, method='POST', **options)

def delete_group(self, group_name, **options):
valid_name = validate_name(group_name)
return self._call('groups/%s' % valid_name, method='DELETE', **options)

def validate_group_name(self, group_name):
slug = unicodedata.normalize('NFKD', group_name)
slug = slug.encode('ascii', 'ignore').lower()
slug = re.sub(r'[^a-z0-9]+', '-', slug).strip('-')
slug = re.sub(r'[-]+', '-', slug)

return slug
94 changes: 94 additions & 0 deletions hapi/lists.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from hapi_plus.base import BaseClient

CONTACTS_API_VERSION = '1'


class ListsClient(BaseClient):

def _get_path(self, subpath):
return 'contacts/v%s/%s' % (CONTACTS_API_VERSION, subpath)

def get_list(self, list_id, **options):
return self._call('lists/%s' % list_id, **options)

def get_batch_lists(self, list_ids, **options):
return self._call('lists/batch', doseq=True, params={'listId': list_ids}, **options)

def get_lists(self, count=20, offset=0, **options):
return self._call('lists', {'count': count, 'offset': offset}, **options)

def get_all_lists(self):
count = 100
has_more = True
offset = 0
lists = []

while has_more:
response = self.get_lists(count=count, offset=offset)
lists.extend(response.get('lists', []))

has_more = response.get('has-more')
offset += response.get('offset')

return lists

def get_static_lists(self, count=20, offset=0, **options):
return self._call('lists/static', {'count': count, 'offset': offset}, **options)

def get_dynamic_lists(self, count=20, offset=0, **options):
return self._call('lists/dynamic', {'count': count, 'offset': offset}, **options)

def get_list_contacts(self, list_id, offset=None, properties=None, count=20, **options):
params = {}

if offset:
params['vidOffset'] = offset

if properties:
params['property'] = properties

if count:
params['count'] = count

return self._call('lists/%s/contacts/all' % list_id, params, doseq=True, **options)

def get_list_contacts_recent(self, list_id, offset=None, properties=None, **options):
params = {}

if offset:
params['timeOffset'] = offset

if properties:
params['property'] = properties

return self._call('lists/%s/contacts/recent' % list_id, params, doseq=True, **options)

def create_list(self, data, **options):
return self._call('lists/', data=data, method='POST', **options)

def update_list(self, list_id, data, **options):
return self._call('lists/%s' % list_id, data=data, method='POST', **options)

def add_contacts_to_list_from_emails(self, list_id, emails, **options):
data = {'emails': emails}
return self._call('lists/%s/add' % list_id, doseq=True, data=data, method='POST', **options)

def add_contact_to_list(self, list_id, contact_id, doseq=True, **options):
data = {'vids': [int(contact_id)]}
return self._call('lists/%s/add' % list_id, data=data, doseq=True, method='POST', **options)

def remove_contact_from_list(self, list_id, contact_id, doseq=True, **options):
data = {'vids': [int(contact_id)]}
return self._call('lists/%s/remove' % list_id, data=data, method='POST', **options)

def delete_list(self, list_id, **options):
return self._call('lists/%s' % list_id, method='DELETE', **options)

def refresh_list(self, list_id, **options):
return self._call('lists/%s/refresh' % list_id, method='POST', **options)

def get_list_intersection(self, include_ids, exclude_ids):
return self._call('lists/intersection/start', doseq=True, params={'include': include_ids, 'exclude': exclude_ids})

def get_list_intersection_status(self, guid):
return self._call('lists/intersection/%s/status' % (guid,))
41 changes: 41 additions & 0 deletions hapi/properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from hapi_plus.base import BaseClient
import unicodedata
import re

PROPERTIES_API_VERSION = '1'


class PropertiesClient(BaseClient):

def _get_path(self, subpath):
return 'contacts/v%s/%s' % (PROPERTIES_API_VERSION, subpath)

def get_property(self, property_name, **options):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a property name validation method which ensures the input is in the proper slug format. this can be done in lue of URL encoding.

valid_name = validate_name(property_name)
return self._call('properties/%s' % valid_name, **options)

def get_properties(self, **options):
return self._call('properties', **options)

def get_grouped_properties(self, **options):
return self._call('properties', {'grouped': True}, **options)

def create_property(self, property_name, data, **options):
valid_name = validate_name(property_name)
return self._call('properties/%s' % valid_name, data=data, method='PUT', **options)

def update_property(self, property_name, data, **options):
valid_name = validate_name(property_name)
return self._call('properties/%s' % valid_name, data=data, method='POST', **options)

def delete_property(self, property_name, **options):
valid_name = validate_property_name)
return self._call('properties/%s' % valid_name, method='DELETE', **options)

def validate_property_name(self, name):
slug = unicodedata.normalize('NFKD', s)
slug = slug.encode('ascii', 'ignore').lower()
slug = re.sub(r'[^a-z0-9]+', '-', slug).strip('-')
slug = re.sub(r'[-]+', '-', slug)

return slug
1 change: 1 addition & 0 deletions hapi/test/hapipy
Submodule hapipy added at 7035b6
Loading