Skip to content

Instantly share code, notes, and snippets.

@samuelharmer
Last active June 29, 2022 21:38
Show Gist options
  • Save samuelharmer/1fe2249b36d86219acb90c1729395b97 to your computer and use it in GitHub Desktop.
Save samuelharmer/1fe2249b36d86219acb90c1729395b97 to your computer and use it in GitHub Desktop.
Amazon Photos, re-run failures

There's no Desktop application for Amazon Photos on Linux. Your only option is to upload through the web user interface.

If you have failures, a <div> pops up in the lower left telling you there are failures, but there's no real way to do anything with that information. Assuming the errors were not serious (e.g. you ran out of upload space for videos) you probably just want to retry the failures: especially if you have 25 thousand files.

The only sensible way to extract the list of failures (there were 170 odd in my case) was to inspect the page and copy the HTML node containing the errors.

This script will take a file containing the paste of the <div> containing the errors and create a new directory with hard links to all the failures. You can then just upload this directory, without consuming any extra disk space. It assumes you have saved the XML file containing the errors to the same file system as the files to upload, otherwise this won't work.

<div class="content-wrapper">
<section class="error-list">
<div class="error-group retryable">
<div class="error">
<div class="file-name">file-1.tif</div>
<div class="error-description">
<span>Network issue</span>
</div>
</div>
<!-- ... -->
</div>
<div class="error-group failed">
<div class="error">
<div class="file-name">Thumbs.db</div>
<div class="error-description">
<span>Invalid file type</span>
</div>
</div>
<!-- ... -->
</div>
</section>
<footer>
<button class="uploader-status-completed-view-previous">
<span>Back</span>
</button>
<div class="calls-to-action">
<button class="uploader-status-completed-retry-all">
<span>Retry all</span>
</button>
</div>
</footer>
</div>
#!/usr/bin/env python3
import os
import sys
import re
from pathlib import Path
from datetime import datetime
from xml.etree.ElementTree import ElementTree
BASE = Path('~/Pictures').expanduser().absolute()
def get_failed_files(failures_xml):
tree = ElementTree()
root = tree.parse(failures_xml)
return [
n.text for n in root.findall(".//div[@class='file-name']")
if not re.match(r'.*\.(db|ini|pdf|txt|doc)$', n.text, re.IGNORECASE)
]
def main():
failures = Path(sys.argv[1])
names = get_failed_files(failures)
paths = sorted([p for p in BASE.rglob('*') if p.name in names])
retry_dir = failures.parent / f"retry.{datetime.now().strftime('%Y%m%dT%H%M%S')}"
for original in paths:
tail = original.relative_to(BASE)
link = retry_dir / tail
link.parent.mkdir(parents=True, exist_ok=True)
os.link(original, link)
print(f'{link} -> {original}')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment