Adding the command line wrapper, to allow shell script usage, and other applications to use pyicloud services.
This commit is contained in:
parent
d86efc04b1
commit
1ca1a84648
2 changed files with 268 additions and 0 deletions
263
pyicloud/cmdline.py
Executable file
263
pyicloud/cmdline.py
Executable file
|
@ -0,0 +1,263 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
A Command Line Wrapper to allow easy use of pyicloud for
|
||||||
|
command line scripts, and related.
|
||||||
|
"""
|
||||||
|
import argparse
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
import pyicloud
|
||||||
|
|
||||||
|
|
||||||
|
DEVICE_ERROR = (
|
||||||
|
"Please use the --device switch to indicate which device to use."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_pickled_data(idevice, filename):
|
||||||
|
"""This helper will output the idevice to a pickled file named
|
||||||
|
after the passed filename.
|
||||||
|
|
||||||
|
This allows the data to be used without resorting to screen / pipe
|
||||||
|
scrapping. """
|
||||||
|
data = {}
|
||||||
|
for x in idevice.content:
|
||||||
|
data[x] = idevice.content[x]
|
||||||
|
location = filename
|
||||||
|
pickle_file = open(location, 'wb')
|
||||||
|
pickle.dump(data, pickle_file, protocol=pickle.HIGHEST_PROTOCOL)
|
||||||
|
pickle_file.close()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
""" Main Function """
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Find My iPhone CommandLine Tool")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--username",
|
||||||
|
action="store",
|
||||||
|
dest="username",
|
||||||
|
default="",
|
||||||
|
help="Apple ID to Use"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--password",
|
||||||
|
action="store",
|
||||||
|
dest="password",
|
||||||
|
default="",
|
||||||
|
help="Apple ID Password to Use",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--list",
|
||||||
|
action="store_true",
|
||||||
|
dest="list",
|
||||||
|
default=False,
|
||||||
|
help="Short Listings for Device(s) associated with account",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--llist",
|
||||||
|
action="store_true",
|
||||||
|
dest="longlist",
|
||||||
|
default=False,
|
||||||
|
help="Detailed Listings for Device(s) associated with account",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--locate",
|
||||||
|
action="store_true",
|
||||||
|
dest="locate",
|
||||||
|
default=False,
|
||||||
|
help="Retrieve Location for the iDevice (non-exclusive).",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Restrict actions to a specific devices UID / DID
|
||||||
|
parser.add_argument(
|
||||||
|
"--device",
|
||||||
|
action="store",
|
||||||
|
dest="device_id",
|
||||||
|
default=False,
|
||||||
|
help="Only effect this device",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Trigger Sound Alert
|
||||||
|
parser.add_argument(
|
||||||
|
"--sound",
|
||||||
|
action="store_true",
|
||||||
|
dest="sound",
|
||||||
|
default=False,
|
||||||
|
help="Play a sound on the device",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Trigger Message w/Sound Alert
|
||||||
|
parser.add_argument(
|
||||||
|
"--message",
|
||||||
|
action="store",
|
||||||
|
dest="message",
|
||||||
|
default=False,
|
||||||
|
help="Optional Text Message to display with a sound",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Trigger Message (without Sound) Alert
|
||||||
|
parser.add_argument(
|
||||||
|
"--silentmessage",
|
||||||
|
action="store",
|
||||||
|
dest="silentmessage",
|
||||||
|
default=False,
|
||||||
|
help="Optional Text Message to display with no sounds",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Lost Mode
|
||||||
|
parser.add_argument(
|
||||||
|
"--lostmode",
|
||||||
|
action="store_true",
|
||||||
|
dest="lostmode",
|
||||||
|
default=False,
|
||||||
|
help="Enable Lost mode for the device",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--lostphone",
|
||||||
|
action="store",
|
||||||
|
dest="lost_phone",
|
||||||
|
default=False,
|
||||||
|
help="Phone Number allowed to call when lost mode is enabled",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--lostpassword",
|
||||||
|
action="store",
|
||||||
|
dest="lost_password",
|
||||||
|
default=False,
|
||||||
|
help="Forcibly active this passcode on the idevice",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--lostmessage",
|
||||||
|
action="store",
|
||||||
|
dest="lost_message",
|
||||||
|
default="",
|
||||||
|
help="Forcibly display this message when activating lost mode.",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Output device data to an pickle file
|
||||||
|
parser.add_argument(
|
||||||
|
"--outputfile",
|
||||||
|
action="store_true",
|
||||||
|
dest="output_to_file",
|
||||||
|
default="",
|
||||||
|
help="Save device data to a file in the current directory.",
|
||||||
|
)
|
||||||
|
|
||||||
|
command_line = parser.parse_args()
|
||||||
|
if not command_line.username or not command_line.password:
|
||||||
|
parser.error('No username or password supplied')
|
||||||
|
|
||||||
|
from pyicloud import PyiCloudService
|
||||||
|
try:
|
||||||
|
api = PyiCloudService(
|
||||||
|
command_line.username.strip(),
|
||||||
|
command_line.password.strip()
|
||||||
|
)
|
||||||
|
except pyicloud.exceptions.PyiCloudFailedLoginException:
|
||||||
|
raise RuntimeError('Bad username or password')
|
||||||
|
|
||||||
|
for dev in api.devices:
|
||||||
|
if (
|
||||||
|
not command_line.device_id
|
||||||
|
or (
|
||||||
|
command_line.device_id.strip().lower()
|
||||||
|
== dev.content["id"].strip().lower()
|
||||||
|
)
|
||||||
|
):
|
||||||
|
# List device(s)
|
||||||
|
if command_line.locate:
|
||||||
|
dev.location()
|
||||||
|
|
||||||
|
if command_line.output_to_file:
|
||||||
|
create_pickled_data(
|
||||||
|
dev,
|
||||||
|
filename=(
|
||||||
|
dev.content["name"].strip().lower() + ".fmip_snapshot"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
contents = dev.content
|
||||||
|
if command_line.longlist:
|
||||||
|
print "-"*30
|
||||||
|
print contents["name"]
|
||||||
|
for x in contents:
|
||||||
|
print "%20s - %s" % (x, contents[x])
|
||||||
|
elif command_line.list:
|
||||||
|
# print "\n"
|
||||||
|
print "-"*30
|
||||||
|
print "Name - %s" % contents["name"]
|
||||||
|
print "Display Name - %s" % contents["deviceDisplayName"]
|
||||||
|
print "Location - %s" % contents["location"]
|
||||||
|
print "Battery Level - %s" % contents["batteryLevel"]
|
||||||
|
print "Battery Status- %s" % contents["batteryStatus"]
|
||||||
|
print "Device Class - %s" % contents["deviceClass"]
|
||||||
|
print "Device Model - %s" % contents["deviceModel"]
|
||||||
|
|
||||||
|
# Play a Sound on a device
|
||||||
|
if command_line.sound:
|
||||||
|
if command_line.device_id:
|
||||||
|
dev.play_sound()
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"\n\n\t\t%s %s\n\n" % (
|
||||||
|
"Sounds can only be played on a singular device.",
|
||||||
|
DEVICE_ERROR
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Display a Message on the device
|
||||||
|
if command_line.message:
|
||||||
|
if command_line.device_id:
|
||||||
|
dev.display_message(
|
||||||
|
subject='A Message',
|
||||||
|
message=command_line.message,
|
||||||
|
sounds=True
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"%s %s" % (
|
||||||
|
"Messages can only be played "
|
||||||
|
"on a singular device.",
|
||||||
|
DEVICE_ERROR
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Display a Silent Message on the device
|
||||||
|
if command_line.silentmessage:
|
||||||
|
if command_line.device_id:
|
||||||
|
dev.display_message(
|
||||||
|
subject='A Silent Message',
|
||||||
|
message=command_line.silentmessage,
|
||||||
|
sounds=False
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"%s %s" % (
|
||||||
|
"Silent Messages can only be played "
|
||||||
|
"on a singular device.",
|
||||||
|
DEVICE_ERROR
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Enable Lost mode
|
||||||
|
if command_line.lostmode:
|
||||||
|
if command_line.device_id:
|
||||||
|
dev.lost_device(
|
||||||
|
number=command_line.lost_phone.strip(),
|
||||||
|
text=command_line.lost_message.strip(),
|
||||||
|
newpasscode=command_line.lost_password.strip()
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
"%s %s" % (
|
||||||
|
"Lost Mode can only be activated "
|
||||||
|
"on a singular device.",
|
||||||
|
DEVICE_ERROR
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
5
setup.py
5
setup.py
|
@ -25,4 +25,9 @@ setup(
|
||||||
'Programming Language :: Python :: 2.7',
|
'Programming Language :: Python :: 2.7',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
],
|
],
|
||||||
|
entry_points={
|
||||||
|
'console_scripts': [
|
||||||
|
'icloud = pyicloud.cmdline:main'
|
||||||
|
]
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue