Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_logger_output(self):
logger = setup_logger()
test_logger = logging.getLogger("icloudpd-test")
string_io = StringIO()
string_handler = logging.StreamHandler(stream=string_io)
string_handler.setFormatter(logger.handlers[0].formatter)
test_logger.addHandler(string_handler)
test_logger.setLevel(logging.DEBUG)
test_logger.info(u"Test info output")
test_logger.debug(u"Test debug output")
test_logger.error(u"Test error output")
output = string_io.getvalue().strip()
self.assertIn("2018-01-01", output)
self.assertIn("INFO Test info output", output)
self.assertIn("DEBUG Test debug output", output)
self.assertIn("ERROR Test error output", output)
def get_photo_exif(path):
"""Get EXIF date for a photo, return nothing if there is an error"""
try:
exif_dict = piexif.load(path)
return exif_dict.get("Exif").get(36867)
except (ValueError, InvalidImageDataError):
logger = setup_logger()
logger.debug("Error fetching EXIF data for %s", path)
return None
def download_media(icloud, photo, download_path, size):
"""Download the photo to path, with retries and error handling"""
logger = setup_logger()
for retries in range(constants.MAX_RETRIES):
try:
photo_response = photo.download(size)
if photo_response:
with open(download_path, "wb") as file_obj:
for chunk in photo_response.iter_content(chunk_size=1024):
if chunk:
file_obj.write(chunk)
update_mtime(photo, download_path)
return True
logger.tqdm_write(
"Could not find URL to download %s for size %s!"
% (photo.filename, size),
logging.ERROR,
def set_photo_exif(path, date):
"""Set EXIF date on a photo, do nothing if there is an error"""
try:
exif_dict = piexif.load(path)
exif_dict.get("1st")[306] = date
exif_dict.get("Exif")[36867] = date
exif_dict.get("Exif")[36868] = date
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, path)
except (ValueError, InvalidImageDataError):
logger = setup_logger()
logger.debug("Error setting EXIF data for %s", path)
return
auto_delete,
only_print_filenames,
folder_structure,
set_exif_datetime,
smtp_username,
smtp_password,
smtp_host,
smtp_port,
smtp_no_tls,
notification_email,
log_level,
no_progress_bar,
notification_script,
):
"""Download all iCloud photos to a local directory"""
logger = setup_logger()
if only_print_filenames:
logger.disabled = True
else:
# Need to make sure disabled is reset to the correct value,
# because the logger instance is shared between tests.
logger.disabled = False
if log_level == "debug":
logger.setLevel(logging.DEBUG)
elif log_level == "info":
logger.setLevel(logging.INFO)
elif log_level == "error":
logger.setLevel(logging.ERROR)
raise_error_on_2sa = (
smtp_username is not None
or notification_email is not None
def autodelete_photos(icloud, folder_structure, directory):
"""
Scans the "Recently Deleted" folder and deletes any matching files
from the download directory.
(I.e. If you delete a photo on your phone, it's also deleted on your computer.)
"""
logger = setup_logger()
logger.info("Deleting any files found in 'Recently Deleted'...")
recently_deleted = icloud.photos.albums["Recently Deleted"]
for media in recently_deleted:
created_date = media.created
date_path = folder_structure.format(created_date)
download_dir = os.path.join(directory, date_path)
for size in [None, "original", "medium", "thumb"]:
path = local_download_path(media, size, download_dir)
if os.path.exists(path):
logger.info("Deleting %s!", path)
os.remove(path)
def authenticate(
username,
password,
cookie_directory=None,
raise_error_on_2sa=False,
client_id=None
):
"""Authenticate with iCloud username and password"""
logger = setup_logger()
logger.debug("Authenticating...")
try:
# If password not provided on command line variable will be set to None
# and PyiCloud will attempt to retrieve from it's keyring
icloud = pyicloud_ipd.PyiCloudService(
username, password,
cookie_directory=cookie_directory,
client_id=client_id)
except pyicloud_ipd.exceptions.NoStoredPasswordAvailable:
# Prompt for password if not stored in PyiCloud's keyring
password = click.prompt("iCloud Password", hide_input=True)
icloud = pyicloud_ipd.PyiCloudService(
username, password,
cookie_directory=cookie_directory,
client_id=client_id)
def send_2sa_notification(
smtp_email, smtp_password, smtp_host, smtp_port, smtp_no_tls, to_addr
):
"""Send an email notification when 2SA is expired"""
to_addr = to_addr if to_addr else smtp_email
from_addr = smtp_email if smtp_email else to_addr
logger = setup_logger()
logger.info("Sending 'two-step expired' notification via email...")
smtp = smtplib.SMTP()
smtp.set_debuglevel(0)
smtp.connect(smtp_host, smtp_port)
if not smtp_no_tls:
smtp.starttls()
if smtp_email is not None or smtp_password is not None:
smtp.login(smtp_email, smtp_password)
subj = "icloud_photos_downloader: Two step authentication has expired"
date = datetime.datetime.now().strftime("%d/%m/%Y %H:%M")
message_text = """Hello,
Two-step authentication has expired for the icloud_photos_downloader script.