Giter Site home page Giter Site logo

pyicloud's Introduction

pyiCloud

Check out our test status at https://travis-ci.org/picklepete/pyicloud

Library version

Supported versions

Downloads

Requirements Status

Formated with Black

Join the chat at https://gitter.im/picklepete/pyicloud

PyiCloud is a module which allows pythonistas to interact with iCloud webservices. It's powered by the fantastic requests HTTP library.

At its core, PyiCloud connects to iCloud using your username and password, then performs calendar and iPhone queries against their API.

Authentication

Authentication without using a saved password is as simple as passing your username and password to the PyiCloudService class:

from pyicloud import PyiCloudService
api = PyiCloudService('[email protected]', 'password')

In the event that the username/password combination is invalid, a PyiCloudFailedLoginException exception is thrown.

You can also store your password in the system keyring using the command-line tool:

$ icloud [email protected]
ICloud Password for [email protected]:
Save password in keyring? (y/N)

If you have stored a password in the keyring, you will not be required to provide a password when interacting with the command-line tool or instantiating the PyiCloudService class for the username you stored the password for.

api = PyiCloudService('[email protected]')

If you would like to delete a password stored in your system keyring, you can clear a stored password using the --delete-from-keyring command-line option:

$ icloud [email protected] --delete-from-keyring

Note: Authentication will expire after an interval set by Apple, at which point you will have to re-authenticate. This interval is currently two months.

Two-step and two-factor authentication (2SA/2FA)

If you have enabled two-factor authentications (2FA) or two-step authentication (2SA) for the account you will have to do some extra work:

if api.requires_2fa:
    print("Two-factor authentication required.")
    code = input("Enter the code you received of one of your approved devices: ")
    result = api.validate_2fa_code(code)
    print("Code validation result: %s" % result)

    if not result:
        print("Failed to verify security code")
        sys.exit(1)

    if not api.is_trusted_session:
        print("Session is not trusted. Requesting trust...")
        result = api.trust_session()
        print("Session trust result %s" % result)

        if not result:
            print("Failed to request trust. You will likely be prompted for the code again in the coming weeks")
elif api.requires_2sa:
    import click
    print("Two-step authentication required. Your trusted devices are:")

    devices = api.trusted_devices
    for i, device in enumerate(devices):
        print(
            "  %s: %s" % (i, device.get('deviceName',
            "SMS to %s" % device.get('phoneNumber')))
        )

    device = click.prompt('Which device would you like to use?', default=0)
    device = devices[device]
    if not api.send_verification_code(device):
        print("Failed to send verification code")
        sys.exit(1)

    code = click.prompt('Please enter validation code')
    if not api.validate_verification_code(device, code):
        print("Failed to verify verification code")
        sys.exit(1)

Devices

You can list which devices associated with your account by using the devices property:

>>> api.devices
{
'i9vbKRGIcLYqJnXMd1b257kUWnoyEBcEh6yM+IfmiMLh7BmOpALS+w==': <AppleDevice(iPhone 4S: Johnny Appleseed's iPhone)>,
'reGYDh9XwqNWTGIhNBuEwP1ds0F/Lg5t/fxNbI4V939hhXawByErk+HYVNSUzmWV': <AppleDevice(MacBook Air 11": Johnny Appleseed's MacBook Air)>
}

and you can access individual devices by either their index, or their ID:

>>> api.devices[0]
<AppleDevice(iPhone 4S: Johnny Appleseed's iPhone)>
>>> api.devices['i9vbKRGIcLYqJnXMd1b257kUWnoyEBcEh6yM+IfmiMLh7BmOpALS+w==']
<AppleDevice(iPhone 4S: Johnny Appleseed's iPhone)>

or, as a shorthand if you have only one associated apple device, you can simply use the iphone property to access the first device associated with your account:

>>> api.iphone
<AppleDevice(iPhone 4S: Johnny Appleseed's iPhone)>

Note: the first device associated with your account may not necessarily be your iPhone.

Find My iPhone

Once you have successfully authenticated, you can start querying your data!

Location

Returns the device's last known location. The Find My iPhone app must have been installed and initialized.

>>> api.iphone.location()
{'timeStamp': 1357753796553, 'locationFinished': True, 'longitude': -0.14189, 'positionType': 'GPS', 'locationType': None, 'latitude': 51.501364, 'isOld': False, 'horizontalAccuracy': 5.0}

Status

The Find My iPhone response is quite bloated, so for simplicity's sake this method will return a subset of the properties.

>>> api.iphone.status()
{'deviceDisplayName': 'iPhone 5', 'deviceStatus': '200', 'batteryLevel': 0.6166913, 'name': "Peter's iPhone"}

If you wish to request further properties, you may do so by passing in a list of property names.

Play Sound

Sends a request to the device to play a sound, if you wish pass a custom message you can do so by changing the subject arg.

api.iphone.play_sound()

A few moments later, the device will play a ringtone, display the default notification ("Find My iPhone Alert") and a confirmation email will be sent to you.

Lost Mode

Lost mode is slightly different to the "Play Sound" functionality in that it allows the person who picks up the phone to call a specific phone number without having to enter the passcode. Just like "Play Sound" you may pass a custom message which the device will display, if it's not overridden the custom message of "This iPhone has been lost. Please call me." is used.

phone_number = '555-373-383'
message = 'Thief! Return my phone immediately.'
api.iphone.lost_device(phone_number, message)

Calendar

The calendar webservice currently only supports fetching events.

Events

Returns this month's events:

api.calendar.events()

Or, between a specific date range:

from_dt = datetime(2012, 1, 1)
to_dt = datetime(2012, 1, 31)
api.calendar.events(from_dt, to_dt)

Alternatively, you may fetch a single event's details, like so:

api.calendar.get_event_detail('CALENDAR', 'EVENT_ID')

Contacts

You can access your iCloud contacts/address book through the contacts property:

>>> for c in api.contacts.all():
>>> print(c.get('firstName'), c.get('phones'))
John [{'field': '+1 555-55-5555-5', 'label': 'MOBILE'}]

Note: These contacts do not include contacts federated from e.g. Facebook, only the ones stored in iCloud.

File Storage (Ubiquity)

You can access documents stored in your iCloud account by using the files property's dir method:

>>> api.files.dir()
['.do-not-delete',
 '.localized',
 'com~apple~Notes',
 'com~apple~Preview',
 'com~apple~mail',
 'com~apple~shoebox',
 'com~apple~system~spotlight'
]

You can access children and their children's children using the filename as an index:

>>> api.files['com~apple~Notes']
<Folder: 'com~apple~Notes'>
>>> api.files['com~apple~Notes'].type
'folder'
>>> api.files['com~apple~Notes'].dir()
['Documents']
>>> api.files['com~apple~Notes']['Documents'].dir()
['Some Document']
>>> api.files['com~apple~Notes']['Documents']['Some Document'].name
'Some Document'
>>> api.files['com~apple~Notes']['Documents']['Some Document'].modified
datetime.datetime(2012, 9, 13, 2, 26, 17)
>>> api.files['com~apple~Notes']['Documents']['Some Document'].size
1308134
>>> api.files['com~apple~Notes']['Documents']['Some Document'].type
'file'

And when you have a file that you'd like to download, the open method will return a response object from which you can read the content.

>>> api.files['com~apple~Notes']['Documents']['Some Document'].open().content
'Hello, these are the file contents'

Note: the object returned from the above open method is a response object and the open method can accept any parameters you might normally use in a request using requests.

For example, if you know that the file you're opening has JSON content:

>>> api.files['com~apple~Notes']['Documents']['information.json'].open().json()
{'How much we love you': 'lots'}
>>> api.files['com~apple~Notes']['Documents']['information.json'].open().json()['How much we love you']
'lots'

Or, if you're downloading a particularly large file, you may want to use the stream keyword argument, and read directly from the raw response object:

>>> download = api.files['com~apple~Notes']['Documents']['big_file.zip'].open(stream=True)
>>> with open('downloaded_file.zip', 'wb') as opened_file:
        opened_file.write(download.raw.read())

File Storage (iCloud Drive)

You can access your iCloud Drive using an API identical to the Ubiquity one described in the previous section, except that it is rooted at `api.drive`:

>>> api.drive.dir()
['Holiday Photos', 'Work Files']
>>> api.drive['Holiday Photos']['2013']['Sicily'].dir()
['DSC08116.JPG', 'DSC08117.JPG']

>>> drive_file = api.drive['Holiday Photos']['2013']['Sicily']['DSC08116.JPG']
>>> drive_file.name
'DSC08116.JPG'
>>> drive_file.date_modified
datetime.datetime(2013, 3, 21, 12, 28, 12) # NB this is UTC
>>> drive_file.size
2021698
>>> drive_file.type
'file'

The open method will return a response object from which you can read the file's contents:

from shutil import copyfileobj
with drive_file.open(stream=True) as response:
    with open(drive_file.name, 'wb') as file_out:
        copyfileobj(response.raw, file_out)

To interact with files and directions the mkdir, rename and delete functions are available for a file or folder:

api.drive['Holiday Photos'].mkdir('2020')
api.drive['Holiday Photos']['2020'].rename('2020_copy')
api.drive['Holiday Photos']['2020_copy'].delete()

The upload method can be used to send a file-like object to the iCloud Drive:

with open('Vacation.jpeg', 'rb') as file_in:
    api.drive['Holiday Photos'].upload(file_in)

It is strongly suggested to open file handles as binary rather than text to prevent decoding errors further down the line.

Photo Library

You can access the iCloud Photo Library through the photos property.

>>> api.photos.all
<PhotoAlbum: 'All Photos'>

Individual albums are available through the albums property:

>>> api.photos.albums['Screenshots']
<PhotoAlbum: 'Screenshots'>

Which you can iterate to access the photo assets. The 'All Photos' album is sorted by added_date so the most recently added photos are returned first. All other albums are sorted by asset_date (which represents the exif date) :

>>> for photo in api.photos.albums['Screenshots']:
        print(photo, photo.filename)
<PhotoAsset: id=AVbLPCGkp798nTb9KZozCXtO7jds> IMG_6045.JPG

To download a photo use the download method, which will return a response object, initialized with stream set to True, so you can read from the raw response object:

photo = next(iter(api.photos.albums['Screenshots']), None)
download = photo.download()
with open(photo.filename, 'wb') as opened_file:
    opened_file.write(download.raw.read())

Note: Consider using shutil.copyfile or another buffered strategy for downloading the file so that the whole file isn't read into memory before writing.

Information about each version can be accessed through the versions property:

>>> photo.versions.keys()
['medium', 'original', 'thumb']

To download a specific version of the photo asset, pass the version to download():

download = photo.download('thumb')
with open(photo.versions['thumb']['filename'], 'wb') as thumb_file:
    thumb_file.write(download.raw.read())

Code samples

If you wanna see some code samples see the code samples file.

pyicloud's People

Contributors

balloob avatar bart274 avatar bschollnick avatar chadj avatar coddingtonbear avatar derphilipp avatar felciano avatar fizix avatar gcobb321 avatar gitter-badger avatar ixs avatar jfburdet avatar k2on avatar longhanks avatar martinhjelmare avatar mchonofsky avatar mohd-akram avatar morrolan avatar ndbroadbent avatar nzapponi avatar philipbl avatar picklepete avatar quentame avatar richieb2b avatar satetsu888 avatar serii833 avatar simonellistonball avatar torarnv avatar walchko avatar yannickulrich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyicloud's Issues

Calendar pGuid Titles

Do you see a possibility to add some sort of function that allows extracting/converting the pGuid from an event to its calendar name?

I have a calendar pGuid like this:
7502832C-B9C6-4218-BC61-03594630219A

And the calendar is called:
"Flights"

It returns the proper name for "home" in pGuid, but not for the other calendars. I tried to look it up myself, but wasn't sure which API you were using there, couldn't find anything over at Apple.

Unable to get Lost_Device to lock iPhone & display message

Here's a example.

test = pyicloud.PyiCloudService ("[email protected]", "password234")
test.devices[5].lost_device ( "5855552349", "testing")

I see the location services activate on the iPhone, but the screen doesn't lock, nor does the testing message appear on the device.

test.devices[5].play_sound ("testing!")

Does work properly. So it appears to be an issue with the lost_device code.

Error when trying to access api.files.dir()

I can login and run the api.devices and api.devices[1].play_sound, but when I try and run any of the other services like api.files.dir() I get the following errors...

>>> api.files.dir()
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:768: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/ubiquity.py", line 51, in __getattr__
    return getattr(self.root, attr)
  File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/ubiquity.py", line 47, in root
    self._root = self.get_node(0)
  File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/ubiquity.py", line 28, in get_node
    return UbiquityNode(self, request.json())
  File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 819, in json
    return json.loads(self.text, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/simplejson/__init__.py", line 505, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python2.7/dist-packages/simplejson/decoder.py", line 370, in decode
    obj, end = self.raw_decode(s)
  File "/usr/local/lib/python2.7/dist-packages/simplejson/decoder.py", line 400, in raw_decode
    return self.scan_once(s, idx=_w(s, idx).end())
simplejson.scanner.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Running python2.7.6 & requests 2.7.0

'com~apple~Notes' not showing up

Hi, thanks for this great work! I can't seem to get access to iCloud notes.

When I try....
api.files.dir()

I get
['comapplePreview', 'comappleTextEdit', 'comappleTextInput', 'comapplefinder', 'comapplemail']

But no 'comappleNotes'. Any ideas? Thanks!

iphone() doesn't always return your iPhone

When I follow your example for getting all of my devices, my daughter's iTouch is the first device listed for some reason. Therefore, when I use your iphone method, her iTouch comes up. Is there a way you segment them by: iPod, iTouch, iPad, iPhone, etc and then iPhone would get all iPhones in my account?

>>> for i in api.devices: print i
... 
iPod: Sammie's iTouch
iPhone 5s: Nina's iPhone
iPad Air 2: Star Lord
iPhone 5s: Sith-5S
iPhone 4s: Jedi-4S
iPad 2: Iron Man
iPad Air: Ninas iPad 
iPad 2: Ninas iPad
iPod: Mike iPod touch
MacBook Pro 13": Tardis
iPod: Kids's iPod touch
iPhone 4s: iPhone
iMac 21.5": Dalek

Stale location

Hello, it looks like pyicloud is often returning a stale location when I query for location. The following situation results in a stale location almost always -- if you are not actively using your iPhone for a while and you are out of your LAN. To test, I logged into the iCloud interface on the web - that too shows the old location, but after a while updates to the new one. So my guess is the pyicloud is not waiting for a refresh (though I see you doing a refresh in the code). Do you know know to fix this?

status fields

does anybody know the possible values of the deviceStatus and their meanings?
I would also love to know what other fields we can ask using the status function?

logging-in not possible

Running

from pyicloud import PyiCloudService
api = PyiCloudService('user', 'code')

gives the error:

File "C:/lku/FindMyIPhone/example.py", line 6, in
api = PyiCloudService('user', 'code')
File "build\bdist.win32\egg\pyicloud\base.py", line 50, in init
File "build\bdist.win32\egg\pyicloud\base.py", line 75, in authenticate
File "build\bdist.win32\egg\pyicloud\base.py", line 66, in refresh_validate
KeyError: 'instance'

I get error on running api.files.dir()

from pyicloud import PyiCloudService
api = PyiCloudService('ID', 'password')
api.files.dir()

{u'reason': u'Invalid global session', u'error': 2}
Traceback (most recent call last):
File "", line 1, in
File "pyicloud/services/ubiquity.py", line 96, in dir
return [child.name for child in self.get_children()]
File "pyicloud/services/ubiquity.py", line 78, in get_children
self._children = self.connection.get_children(self.item_id)
File "pyicloud/services/ubiquity.py", line 35, in get_children
items = request.json()['item_list']
KeyError: 'item_list'

Support two-factor/two-step authentication

When enabling two-factor/two-step authentication most services fail with an error response of Missing X-APPLE-WEBAUTH-TOKEN cookie. Unfortunately, since icloud.com is an Apple service, single app passwords do not work.

The login response has hsaChallengeRequired set to True and we need to issue calls to the sendVerificationCode and validateVerificationCode endpoints based on a device the user chooses. This probably needs to happen interactively, so pyicloud should have the appropriate APIs for clients to be able to support this flow.

How we can get the address book of the user

Hi ,

Can you please let me know how we can retrieve the address book of the user using pyicloud ??

Appreciate your support and waiting for your response.

Regards,
Gaurav

"Computer" support ?

Hello,

I've tried to use pyicloud to lock my computer, but it did not work (no matter the arguments?)

Is this a known issue, or is there some way I can help ?

Best regards,

EDIT1/ Looks like what I want/need is this: /fmipservice/client/web/remoteLock

Please upload latest version to PyPI

Hi there, @picklepete!

I've noticed that you haven't updated the version on PyPI in some time. Now that the version number has been bumped to 0.3.0, I wonder if I could convince you into uploading the latest version to PyPI. You can do that from your local copy of the repository simply by running:

python setup.py sdist upload

This allows people like me to mark the proper version of this library as a dependency in our libraries' requirements.txt files* so that the installation process for libraries depending upon this will automatically fetch the proper version from PyPI.

Let me know if you have any questions (you can ping me on gtalk -- [email protected], or freenode -- coddingtonbear).

Cheers!
Adam

  • You'll notice in the linked requirements.txt, I've a dependency named pyicloud_dwoh; that is a version of pyicloud I forked and independently uploaded to work around this limitation.

iCloud Photos "update" action needed before calling photos.all()

I noticed that the photos.all() function was not returning some recent photos in my library.

After logging into icloud.com and clicking the "update" button at the bottom of the photo library (the text that says "xxxx photos and videos; last updated yyyy") The recent photos appeared in my library and were then available to photos.all()

Took some time trying to figure out what's going on in the javascript debugger, but this isn't really my area of expertise, and I didn't make any progress.

Consider this a feature request to add a "update()" action to the photos service so that the library can be synched prior to calling photos.all()

Thanks for your efforts.

Every time I connect to API from python script, Apple sends me email

Hello,

I am getting a "Your Apple ID was used to sign in to iCloud via a web browser" literally every time my pyicloud script connects. Any way to prevent that? I'd like check my iPhone's location regularly throughout the day with a cron job, but that doesn't seem practical if Apple is going to treat every connection as though it's from a previously unknown browser.

Thanks,
Thomas

Recent changes to iCloud API prevent one from logging-in successfully

>>> from pyicloud import PyiCloudService
>>> s = PyiCloudService(my_username, my_password)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/adamcoddington/Documents/Projects/pyicloud/pyicloud/base.py", line 50, in __init__
    self.authenticate()
  File "/Users/adamcoddington/Documents/Projects/pyicloud/pyicloud/base.py", line 75, in authenticate
    self.refresh_validate()
  File "/Users/adamcoddington/Documents/Projects/pyicloud/pyicloud/base.py", line 66, in refresh_validate
    instance = resp['instance']
KeyError: 'instance'
>>>

How do you choose a device for location?

How do you pick which device from your list of devices when using the location function. I can only seem to figure out how to get it to return the location of the first device on my list.

findmyiphone.py not always returning battery level?

Hi,

Is there a reason why the findmyiphone.py isn't always returning the battery level?
pyicloud is used in Home Assistant to track the device of my account and of the account of my girlfriend.
When I look at the data I receive, my battery levels of both my iPhone and iPad are being received, but the battery levels of both my girlfriends iPhone and iPad aren't being received at all.
Her account used to be linked to my family on iCloud and then I could see her battery levels as well.
The reason I removed her account from my family is because I want to update my data each 5 minutes and hers only each 15 minutes (my iPhone is plugged in at work, hers isn't).

Porting code to php

Hey guys, I'm trying to port this to php to get away from annoying shell exec in my app.
I'm having problems with (I assume) generating id.
Here is the current code: https://gist.github.com/cvele/b485eec10d16d155c723

Everything seems to go swimmingly until request to _fmip_refresh_url is made which results in 450 (?!) http status code.

Curl debug output (a stripped down version) looks like this:
https://gist.github.com/cvele/83b7c9e394fe519d5bc0

Did you guys come across something like this? or do you have any idea on how to get around this?

I do know this is not really good place to post this, as it is not an issue with your code - but I don't really have another way of reaching out.

thanks.

Download data from iclod

Hi Sir,

Please tell me how can i download data from icloud using ubiquity.py as i am able to run Find my iphone command line tool options but not able to use File Storage option please help

i install setup.py and it generate icloud .exe which show option only for Find my iphone command line tool so please help me

as i not know much about python.

thanks

Smart quotes cause --list to fail

Calling icloud --list causes a stack trace with my iCloud account because one of my devices has a smart quote (single backtick) in its name:

Traceback (most recent call last):
  File "/usr/local/bin/icloud", line 9, in <module>
    load_entry_point('pyicloud==0.9.1', 'console_scripts', 'icloud')()
  File "/usr/local/lib/python2.7/site-packages/pyicloud/cmdline.py", line 256, in main
    print("Name - %s" % contents["name"])
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' in position 12: ordinal not in range(128)

Last Known Location

Hey there!

Love the module it's really fantastic!

I was wondering if there is a way to update the location? Getting the last known location is brilliant, but is it possible to do a refresh? You can do such thing on the iCloud website, that way you can live track your phone.

Unfortunately I have not found a way to do this from within the module.

Thanks in advance

Processing the location response

How can I process the "api.iphone.location()" response in Python? I assume the response is in a JSON format, but when I try the following I get an error message:

api = PyiCloudService("XXXXXXX", "XXXXXXXX")
iPhoneLocation = api.devices[iPhoneRene].location()
parsed_json = json.loads(iPhoneLocation)
print(parsed_json['timeStamp'])

File "checkiPhoneAtHome.py", line 15, in
parsed_json = json.loads(iPhoneLocation)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/init.py", line 338, in loads
return _default_decoder.decode(s)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: expected string or buffer

Calendar Retrieval Problem

Hi,
Can anyone shed light on a problem I'm having accessing calendar and contact info. I can connect ok and go through the two stage verification with no problems. I can access info on devices, but when i try to print calendar.events() it fails:

New to this, so expect its something simple i haven't done?

Thanks in advance, Rob

OUTPUT:
{u’**********’: <AppleDevice(iPhone 6 Plus: 7)>, u’**********': <AppleDevice(Mac mini: Cooper)>}

Traceback (most recent call last):
File “iCloud”, line 26, in
print api.calendar.events()
File "/Library/Python/2.7/site-packages/pyicloud-0.8.0-py2.7.egg/pyicloud/services/calendar.py", line 93, in events
self.refresh_client(from_dt, to_dt)
File "/Library/Python/2.7/site-packages/pyicloud-0.8.0-py2.7.egg/pyicloud/services/calendar.py", line 86, in refresh_client
req = self.session.get(self._calendar_refresh_url, params=params)
File "/Library/Python/2.7/site-packages/requests-2.9.1-py2.7.egg/requests/sessions.py", line 480, in get
return self.request('GET', url, **kwargs)
File "/Library/Python/2.7/site-packages/pyicloud-0.8.0-py2.7.egg/pyicloud/base.py", line 71, in request
reason = json.get('errorMessage') or json.get('reason')
AttributeError: 'NoneType' object has no attribute 'get'

code:

from pyicloud import PyiCloudService
import click

api=PyiCloudService(‘_’,’_’)

if api.requires_2fa:
print "Two-factor authentication required. Your trusted devices are:"

devices = api.trusted_devices
for i, device in enumerate(devices):
    print "  %s: %s" % (i, device.get('deviceName',
        "SMS to %s" % device.get('phoneNumber')))

device = click.prompt('Which device would you like to use?', default=0)
device = devices[device]
if not api.send_verification_code(device):
    print "Failed to send verification code"
    sys.exit(1)

code = click.prompt('Please enter validation code')
if not api.validate_verification_code(device, code):
    print "Failed to verify verification code"
    sys.exit(1)

print api.devices
print api.calendar.events()

Installing to Python 3.3 (as of 08/13/13)

I was unable to locate where in the documentation the Python version(s) are specified for pyicloud. I gave it a shot under a virtualenv and Python 3.3. The install presented the following output ...

(py33)bash-3.2$ python setup.py install
running install
running bdist_egg
running egg_info
creating pyicloud.egg-info
writing top-level names to pyicloud.egg-info/top_level.txt
writing pyicloud.egg-info/PKG-INFO
writing requirements to pyicloud.egg-info/requires.txt
writing dependency_links to pyicloud.egg-info/dependency_links.txt
writing manifest file 'pyicloud.egg-info/SOURCES.txt'
reading manifest file 'pyicloud.egg-info/SOURCES.txt'
writing manifest file 'pyicloud.egg-info/SOURCES.txt'
installing library code to build/bdist.macosx-10.6-intel/egg
running install_lib
running build_py
creating build
creating build/lib
creating build/lib/pyicloud
copying pyicloud/init.py -> build/lib/pyicloud
copying pyicloud/base.py -> build/lib/pyicloud
copying pyicloud/exceptions.py -> build/lib/pyicloud
creating build/lib/pyicloud/services
copying pyicloud/services/init.py -> build/lib/pyicloud/services
copying pyicloud/services/calendar.py -> build/lib/pyicloud/services
copying pyicloud/services/findmyiphone.py -> build/lib/pyicloud/services
copying pyicloud/services/ubiquity.py -> build/lib/pyicloud/services
creating build/bdist.macosx-10.6-intel
creating build/bdist.macosx-10.6-intel/egg
creating build/bdist.macosx-10.6-intel/egg/pyicloud
copying build/lib/pyicloud/init.py -> build/bdist.macosx-10.6-intel/egg/pyicloud
copying build/lib/pyicloud/base.py -> build/bdist.macosx-10.6-intel/egg/pyicloud
copying build/lib/pyicloud/exceptions.py -> build/bdist.macosx-10.6-intel/egg/pyicloud
creating build/bdist.macosx-10.6-intel/egg/pyicloud/services
copying build/lib/pyicloud/services/init.py -> build/bdist.macosx-10.6-intel/egg/pyicloud/services
copying build/lib/pyicloud/services/calendar.py -> build/bdist.macosx-10.6-intel/egg/pyicloud/services
copying build/lib/pyicloud/services/findmyiphone.py -> build/bdist.macosx-10.6-intel/egg/pyicloud/services
copying build/lib/pyicloud/services/ubiquity.py -> build/bdist.macosx-10.6-intel/egg/pyicloud/services
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/init.py to init.cpython-33.pyc
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/base.py to base.cpython-33.pyc
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/exceptions.py to exceptions.cpython-33.pyc
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/services/init.py to init.cpython-33.pyc
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/services/calendar.py to calendar.cpython-33.pyc
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/services/findmyiphone.py to findmyiphone.cpython-33.pyc
byte-compiling build/bdist.macosx-10.6-intel/egg/pyicloud/services/ubiquity.py to ubiquity.cpython-33.pyc
creating build/bdist.macosx-10.6-intel/egg/EGG-INFO
copying pyicloud.egg-info/PKG-INFO -> build/bdist.macosx-10.6-intel/egg/EGG-INFO
copying pyicloud.egg-info/SOURCES.txt -> build/bdist.macosx-10.6-intel/egg/EGG-INFO
copying pyicloud.egg-info/dependency_links.txt -> build/bdist.macosx-10.6-intel/egg/EGG-INFO
copying pyicloud.egg-info/requires.txt -> build/bdist.macosx-10.6-intel/egg/EGG-INFO
copying pyicloud.egg-info/top_level.txt -> build/bdist.macosx-10.6-intel/egg/EGG-INFO
zip_safe flag not set; analyzing archive contents...
creating dist
creating 'dist/pyicloud-0.2-py3.3.egg' and adding 'build/bdist.macosx-10.6-intel/egg' to it
removing 'build/bdist.macosx-10.6-intel/egg' (and everything under it)
Processing pyicloud-0.2-py3.3.egg
Copying pyicloud-0.2-py3.3.egg to /Users/cnivcec/Virtuals/py33/lib/python3.3/site-packages
Adding pyicloud 0.2 to easy-install.pth file

Installed /Users/cnivcec/Virtuals/py33/lib/python3.3/site-packages/pyicloud-0.2-py3.3.egg
Processing dependencies for pyicloud==0.2
Searching for requests==1.2.3
Best match: requests 1.2.3
Processing requests-1.2.3-py3.3.egg
requests 1.2.3 is already the active version in easy-install.pth

Using /Users/cnivcec/Virtuals/py33/lib/python3.3/site-packages/requests-1.2.3-py3.3.egg
Finished processing dependencies for pyicloud==0.2
(py33)bash-3.2$

_End of install output_*****

I then tried to import the pyicloud module itself ...

Python 3.3.2 (v3.3.2:d047928ae3f6, May 13 2013, 13:52:24)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

import pyicloud
Traceback (most recent call last):
File "", line 1, in
File "./pyicloud/init.py", line 1, in
from base import PyiCloudService
ImportError: No module named 'base'

_End of import error_**********

Perhaps the path to the base.py file (which I verified as an accessible *.py file) is not being passed to the installer? Total conjecture on my part. Just wanted to get back to you Peter.

I setup virtualenv with Python2.7.5 and the pyicloud module installed without issue. Now for some development.

Thanks again!

How to get the contact details

Hi ,

When i am trying to retrieve the contact details , I am getting object . Can you please help to know how to get the details of my contacts.

Regards,
Gaurav

Upload files

Is it possible to upload a file with the current version? I cannot see any mention of "put" methods in the documentation.
If not, is is something being worked on? or it's just plainly impossible right now
Thanks.

first 1200 photos are fine, "Internal Server Error" on the rest

Any thoughts about this?
`
$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.

from pyicloud import PyiCloudService
api = PyiCloudService('[email protected]')
print('You have %d photos' % (len(api.photos.all.photos)))
You have 1871 photos
print api.photos.all.photos[700].filename
IMG_2013.JPG
print api.photos.all.photos[1700].filename
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/photos.py", line 242, in filename
return self.data['details'].get('filename')
File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/photos.py", line 237, in data
self._data = self.album._fetch_asset_data_for(self)
File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/photos.py", line 205, in _fetch_asset_data_for
self.service._fetch_asset_data_for(client_ids)
File "/usr/local/lib/python2.7/dist-packages/pyicloud/services/photos.py", line 78, in _fetch_asset_data_for
data=data
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 518, in post
return self.request('POST', url, data=data, json=json, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/pyicloud/base.py", line 99, in request
raise api_error
pyicloud.exceptions.PyiCloudAPIResponseError: Internal Server Error (500)

`

Download file

Hi,
I'm trying to download a file .sqlite my iCloud account with pyicloud, but the file I download is always 0 bytes ..
I've tried following the instructions:

download = api.files['comappleNotes']['Documents']['big_file.zip'].open(stream=True)
with open('downloaded_file.zip', 'wb') as opened_file:
opened_file.write(download.raw.read())

but no way, can you help me?

Thank you

get location in cosole DEVICE_ID

hey,

i try the console command

icloud --username [email protected] --password AS3curePw! --locate --device anyUIDfromMYdevice

The output that i became:

/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:789: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:789: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:789: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py:789: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
  InsecureRequestWarning)

The login is fine, i have become a email from apple tha anyone is using my icloud account with the webservice.

can anyont tell me my mistake? I only need the location of my iphone.

Thanks!

Issues with cookielib after updating to 0.7.3

I am getting this error after upgrading to 0.7.3.

ImportError: No module named 'cookielib'

I checked pypi and the code and I am not sure where cookielib is to be installed from.

What am I missing?

CalendarService error

When running a call to api.calendar.events(), I'm getting an error that 'CalendarService' object has no attribute 'get_possible_timezones', which is called on line 53 of calendar.py. Additionally, the function get_all_possible_timezones_of_local_machine returns an empty list.

OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

Hi,

Sometimes when I try to download a file (often a large file) I've got an error. The traceback is:

File "", line 1, in
File "pyicloud/services/ubiquity.py", line 94, in open
return self.connection.get_file(self.item_id, *_kwargs)
File "pyicloud/services/ubiquity.py", line 37, in get_file
*_kwargs
File "/home/.../.local/lib/python2.7/site-packages/requests/sessions.py", line 473, in get
return self.request('GET', url, *_kwargs)
File "/home/.../.local/lib/python2.7/site-packages/requests/sessions.py", line 461, in request
resp = self.send(prep, *_send_kwargs)
File "/home/.../.local/lib/python2.7/site-packages/requests/sessions.py", line 573, in send
r = adapter.send(request, *_kwargs)
File "/home/.../.local/lib/python2.7/site-packages/requests/adapters.py", line 370, in send
timeout=timeout
File "/home/.../.local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 518, in urlopen
body=body, headers=headers)
File "/home/.../.local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 353, in _make_request
httplib_response = conn.getresponse(buffering=True)
File "/usr/lib/python2.7/httplib.py", line 1131, in getresponse
response.begin()
File "/usr/lib/python2.7/httplib.py", line 453, in begin
version, status, reason = self._read_status()
File "/usr/lib/python2.7/httplib.py", line 409, in _read_status
line = self.fp.readline(_MAXLINE + 1)
File "/usr/lib/python2.7/socket.py", line 480, in readline
data = self._sock.recv(self._rbufsize)
File "/home/.../.local/lib/python2.7/site-packages/requests/packages/urllib3/contrib/pyopenssl.py", line 188, in recv
data = self.connection.recv(_args, **kwargs)
File "/usr/lib/python2.7/dist-packages/OpenSSL/SSL.py", line 1320, in recv
self._raise_ssl_error(self._ssl, result)
File "/usr/lib/python2.7/dist-packages/OpenSSL/SSL.py", line 1178, in _raise_ssl_error
raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

Unverified HTTPS request

I'm getting multiple (four) InsecureRequestWarnings from urllib3 on using it with Python 2.7.6.

Can not read icloud photo?

How did you know icloud access API's address?

Where have you read the document?

Now it seems to have no support for reading icloud photographs inside it, can later add it?

Thanks for sharing such a great Python!

play_sound on family member's devices doesn't work?

I have a family account set up, so when I login with my icloud credentials, I see my family's devices. So far so good. But when I try to do a play_sound() with one of my family's device's device id, it doesn't work. I get an internal server error exception. It seems to work for my own devices just fine ("own" === my account is logged in as the icloud account on that device)

Curiously, if I use my family member's credentials to login to their account, I can play_sound() on their device just fine.

In the two cases, the device ID does appear to be different. When I'm logged in as myself, the device id of my family member's phone is much longer than the device ID for my own phone.

Also, other things like reading the family member's phone's location and battery seem to work just fine.

Note on CalendarEvents missing?

Hi there.

Great project you have here! As far as I can tell, the 'note' on an event doesn't seem to be retrieved with

cal.events()

which produces the following entries on each event:

startDate
birthdayLastName
endDate
pGuid
recurrenceMaster
extendedDetailsAreIncluded
duration
birthdayCompanyName
guid
recurrence
tz
title
localEndDate
recurrenceException
birthdayShowAsCompany
etag
location
eventStatus
birthdayFirstName
readOnly
birthdayBirthDate
icon
allDay
hasAttachments
localStartDate
birthdayNickname
birthdayIsYearlessBday
alarms

Am I missing something?

InsecurePlatformWarning:

Hello! I get this warning every time I run the script

A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
InsecurePlatformWarning
/usr/local/lib/python2.7/site-packages/requests-2.6.0-py2.7.egg/requests/packages/urllib3/connectionpool.py:769: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
InsecureRequestWarning)
/usr/local/lib/python2.7/site-packages/requests-2.6.0-py2.7.egg/requests/packages/urllib3/connectionpool.py:769: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
InsecureRequestWarning)
/usr/local/lib/python2.7/site-packages/requests-2.6.0-py2.7.egg/requests/packages/urllib3/connectionpool.py:769: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
InsecureRequestWarning)

Allow session.verify

Could we please have some way to allow session.verify to be True? The attached patch is one possible way.

Hum... I'm getting "Attaching documents requires write permission to this repository. Try again with a PNG, GIF, or JPG." (that's pretty silly!)

Here's the patch inline..

--- pyicloud-svn/base.py        2015-05-29 17:17:37.000000000 -0700
+++ pyicloud/base.py    2015-10-18 17:23:53.000000000 -0700
@@ -32,7 +32,7 @@
         pyicloud = PyiCloudService('[email protected]', 'password')
         pyicloud.iphone.location()
     """
-    def __init__(self, apple_id, password, cookie_directory=None):
+    def __init__(self, apple_id, password, cookie_directory=None, verify=False):
         self.discovery = None
         self.client_id = str(uuid.uuid1()).upper()
         self.user = {'apple_id': apple_id, 'password': password}
@@ -57,7 +57,7 @@
             )
 
         self.session = requests.Session()
-        self.session.verify = False
+        self.session.verify = verify
         self.session.headers.update({
             'host': 'setup.icloud.com',
             'origin': self._home_endpoint,

Photo Stream

Would it be possible to download the photos from the Photo Stream? The ICloud Control Panel is trash, so I'm looking for an alternative.

I'll look into maybe adding the functionality, but if someone already knows how then it would be much appreciated.

Ability to set UUID - given Icloud Security changes

Hi - thanks for this code.

Given Icloud Security changes though - any logon to icloud account results in a somewhat annoying email - per logon.

If the logon clientContext is set to a users existing device via deviceUDID the emails don't come anymore (presumably icloud know it is user authorised device and doesnt send them)

Is it possible to spoof this known client UDID, osVersion and ProductType to avoid these emails?

Thanks

        "clientContext":{
            "appName":"",,
            "buildVersion":"145",
            "deviceUDID":"xxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "inactiveTime":2147483647,
            "osVersion":"7.1.2",
            "personID":0,
            "productType":"iPad4,4"

Any chance to look at this as an option to stop the emails?

Glenn

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.