From 2623013b4811ca3f4071f1564b8f91c05905bd35 Mon Sep 17 00:00:00 2001 From: Mario Mancino Date: Fri, 22 Aug 2014 18:36:06 +0200 Subject: [PATCH 1/2] iCloud Contacts Support, based on pull-request from joachimneu --- pyicloud/base.py | 14 +++++++++++++- pyicloud/services/__init__.py | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pyicloud/base.py b/pyicloud/base.py index 23e774e..739e7bc 100644 --- a/pyicloud/base.py +++ b/pyicloud/base.py @@ -8,7 +8,8 @@ from pyicloud.exceptions import PyiCloudFailedLoginException from pyicloud.services import ( FindMyiPhoneServiceManager, CalendarService, - UbiquityService + UbiquityService, + ContactsService ) @@ -72,6 +73,12 @@ class PyiCloudService(object): ) self.params.update({'id': sha.hexdigest().upper()}) + clientId = str(uuid.uuid1()).upper() + self.params.update({ + 'clientBuildNumber': '14E45', + 'clientId': clientId, + }) + def authenticate(self): """ Handles the full authentication steps, validating, @@ -126,6 +133,11 @@ class PyiCloudService(object): service_root = self.webservices['calendar']['url'] return CalendarService(service_root, self.session, self.params) + @property + def contacts(self): + service_root = self.webservices['contacts']['url'] + return ContactsService(service_root, self.session, self.params) + def __unicode__(self): return 'iCloud API: %s' % self.user.get('apple_id') diff --git a/pyicloud/services/__init__.py b/pyicloud/services/__init__.py index 3911d9b..4befaf7 100644 --- a/pyicloud/services/__init__.py +++ b/pyicloud/services/__init__.py @@ -1,3 +1,4 @@ from pyicloud.services.calendar import CalendarService from pyicloud.services.findmyiphone import FindMyiPhoneServiceManager from pyicloud.services.ubiquity import UbiquityService +from contacts import ContactsService From 4d4f3c31c7f8c48cf739c9a2e5c9117617209550 Mon Sep 17 00:00:00 2001 From: Mario Mancino Date: Fri, 22 Aug 2014 18:42:44 +0200 Subject: [PATCH 2/2] added Contacts class --- pyicloud/services/contacts.py | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pyicloud/services/contacts.py diff --git a/pyicloud/services/contacts.py b/pyicloud/services/contacts.py new file mode 100644 index 0000000..9208df7 --- /dev/null +++ b/pyicloud/services/contacts.py @@ -0,0 +1,49 @@ +from __future__ import absolute_import +import os +import uuid +from datetime import datetime +from calendar import monthrange + + +class ContactsService(object): + """ + The 'Contacts' iCloud service, connects to iCloud and returns contacts. + """ + def __init__(self, service_root, session, params): + self.session = session + self.params = params + self._service_root = service_root + self._contacts_endpoint = '%s/co' % self._service_root + self._contacts_refresh_url = '%s/startup' % self._contacts_endpoint + self._contacts_changeset_url = '%s/changeset' % self._contacts_endpoint + + def refresh_client(self, from_dt=None, to_dt=None): + """ + Refreshes the ContactsService endpoint, ensuring that the + contacts data is up-to-date. + """ + host = self._service_root.split('//')[1].split(':')[0] + self.session.headers.update({'host': host}) + params_contacts = dict(self.params) + params_contacts.update({ + 'clientVersion': '2.1', + 'locale': 'en_US', + 'order': 'last,first', + }) + req = self.session.get(self._contacts_refresh_url, params=params_contacts) + self.response = req.json() + params_refresh = dict(self.params) + params_refresh.update({ + 'prefToken': req.json()["prefToken"], + 'syncToken': req.json()["syncToken"], + }) + self.session.post(self._contacts_changeset_url, params=params_refresh) + req = self.session.get(self._contacts_refresh_url, params=params_contacts) + self.response = req.json() + + def all(self): + """ + Retrieves all contacts. + """ + self.refresh_client() + return self.response['contacts']