checkdupes cli function, add readme
parent
4f218f068a
commit
6530d86617
|
@ -0,0 +1,54 @@
|
|||
photolib
|
||||
========
|
||||
|
||||
Cloud-native photo and related media library software, with a focus for photography hobbyists.
|
||||
|
||||
TODO longer description
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
After installation, photolib provides a CLI tool, `photocli`. It can be used as follows:
|
||||
|
||||
* `photocli checkdupes` - scan files and print those not already in the library:
|
||||
|
||||
|
||||
```
|
||||
$ find source -type f -exec shasum -a 256 {} \; | tee shas.txt
|
||||
544b5a4f3898abae73260930ee70931a3992c048649692cef89b37576e886f69 source/2018-12-09 13.52.22.jpg
|
||||
d2c2c30ca4986d364026644881d667162031008e60aac6a69d7b18230b7ea98c source/2019-04-08 20.05.02.jpg
|
||||
9d42859ed92d7fb978cf73b41293480e1eab03d2d3a14c185c4daf3a49d324ab source/2019-06-19 16.28.07.png
|
||||
...
|
||||
|
||||
$ photocli -s http://localhost:8080 checkdupes --sha-files shas.txt
|
||||
|
||||
```
|
||||
|
||||
TODO: support not using `--sha-files`
|
||||
|
||||
|
||||
* `photocli ingest` - import new photos into the library:
|
||||
|
||||
|
||||
```
|
||||
$ photocli -s http://localhost:8080 ingest photos/*.jpg raws/*.cr2
|
||||
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
TODO: implement this
|
||||
|
||||
There is some non-obvious behavior in the ingest process that is important to understand. Many photographers shoot in
|
||||
multiple formats, in the sense that one click of the shutter produces multiple formats. Jpeg and Raw is common. During
|
||||
ingest, photocli assumes that files with the same filename are multiple formats of the same image. E.g., if you have
|
||||
both `IMG_1234.JPG` and `IMG_1234.cr2`, the two images will be grouped in the library. This combination action is only
|
||||
applied during ingest; images already in the library that happen to share a filename with a file being imported will
|
||||
not be merged. To add a format to a photo already in the library, see `photocli addformat`.
|
|
@ -1,6 +1,8 @@
|
|||
import argparse
|
||||
import requests
|
||||
from requests.exceptions import HTTPError
|
||||
from photoapp.utils import get_extension
|
||||
from photoapp.types import known_extensions
|
||||
|
||||
|
||||
class PhotoApiClient(object):
|
||||
|
@ -32,7 +34,6 @@ def main():
|
|||
p_ingest.add_argument("-c", "--copy-of", help="existing uuid the imported images will be placed under")
|
||||
|
||||
args = parser.parse_args()
|
||||
print(args)
|
||||
|
||||
client = PhotoApiClient(args.host)
|
||||
|
||||
|
@ -48,20 +49,24 @@ def main():
|
|||
if not line:
|
||||
continue
|
||||
sha, path = line.split(maxsplit=1)
|
||||
hashes[sha] = path.rstrip("\n")
|
||||
path = path.rstrip("\n")
|
||||
if get_extension(path) not in known_extensions:
|
||||
continue
|
||||
hashes[sha] = path
|
||||
else:
|
||||
raise NotImplementedError("must pass --sha-files for now")
|
||||
|
||||
for sha, path in hashes.items():
|
||||
# hit http://localhost:8080/api/v1/byhash?sha=afe49172f709725a4503c9219fb4c6a9db8ad0354fc493f2f500269ac6faeaf6
|
||||
# if the file is a dupe, do nothing
|
||||
# if the file is original, print its path
|
||||
try:
|
||||
print(client.byhash(sha))
|
||||
client.byhash(sha)
|
||||
# if the file is a dupe, do nothing
|
||||
except HTTPError as he:
|
||||
print(repr(he.response.status_code))
|
||||
|
||||
# print(hashes)
|
||||
# if the file is original, print its path
|
||||
if he.response.status_code == 404:
|
||||
print(path)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -4,9 +4,10 @@ import traceback
|
|||
from photoapp.library import PhotoLibrary
|
||||
from photoapp.image import get_jpg_info, get_hash, get_mtime
|
||||
from itertools import chain
|
||||
from photoapp.types import Photo, PhotoSet
|
||||
from photoapp.types import Photo, PhotoSet, known_extensions, regular_images, files_raw, files_video
|
||||
import os
|
||||
|
||||
|
||||
"""
|
||||
Photo sorting rules:
|
||||
|
||||
|
@ -20,11 +21,6 @@ mov, video, or other
|
|||
modification date
|
||||
"""
|
||||
|
||||
known_extensions = ["jpg", "png", "cr2", "xmp", "mp4", "mov"]
|
||||
regular_images = ["jpg", "png"]
|
||||
files_raw = ["cr2", "xmp"]
|
||||
files_video = ["mp4", "mov"]
|
||||
|
||||
|
||||
def pprogress(done, total=None):
|
||||
print(" complete: {}{}\r".format(done, " / {} ".format(total) if total else ''), end='')
|
||||
|
|
|
@ -7,6 +7,12 @@ import uuid
|
|||
import enum
|
||||
|
||||
|
||||
known_extensions = ["jpg", "png", "cr2", "xmp", "mp4", "mov"]
|
||||
regular_images = ["jpg", "png"]
|
||||
files_raw = ["cr2", "xmp"]
|
||||
files_video = ["mp4", "mov"]
|
||||
|
||||
|
||||
class PhotoStatus(enum.Enum):
|
||||
private = 0
|
||||
public = 1
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
import cherrypy
|
||||
from photoapp.types import PhotoSet, PhotoStatus
|
||||
|
||||
|
@ -15,6 +16,13 @@ def mime2ext(mime):
|
|||
"video/quicktime": "mov"}[mime]
|
||||
|
||||
|
||||
def get_extension(fname):
|
||||
parts = os.path.basename(fname).split(".")
|
||||
if len(parts) == 1:
|
||||
return None
|
||||
return parts[-1].lower()
|
||||
|
||||
|
||||
def auth():
|
||||
"""
|
||||
Return the currently authorized username (per request) or None
|
||||
|
|
Loading…
Reference in New Issue