From 5039fb29609ab06697a8a9552b3294fa2ca6b568 Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Fri, 12 Jul 2024 13:16:11 -0400 Subject: add initial external image support --- library_info_cli.py | 106 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 37 deletions(-) diff --git a/library_info_cli.py b/library_info_cli.py index 5416662..e2aeaca 100755 --- a/library_info_cli.py +++ b/library_info_cli.py @@ -12,38 +12,10 @@ # Dependencies: # dep-almalinux8: python3-requests, python3-dateutil -import argparse, sys, json, datetime +import argparse, sys, json, datetime, base64, os import library_info_lib -parser = argparse.ArgumentParser(description="Shows currently checked out items from the configured libraries.") -parser.add_argument("-d","--debug", nargs='?', default=0, type=int, choices=range(0,11), help="Set debug level. >=5 adds verbose=True to get_checkouts().") -# add output option: html, raw, json -# add mutual: all or single. -group1 = parser.add_mutually_exclusive_group() -group1.add_argument("-s","--single", help="Show this single account.") -group1.add_argument("-a","--all", action='store_true', default=True, help="Check all accounts") -parser.add_argument("-o","--output", choices=["html","json","raw"], default="raw", help="Output format.") -try: - # This was only added in python 3.9 - parser.add_argument("-f","--full", action=argparse.BooleanOptionalAction, default=True, help="Use full image objects or not. They are huge and during debugging it is useful to turn off.") -except AttributeError: - group2 = parser.add_mutually_exclusive_group() - group2.add_argument("-f","--full", action="store_true", default=True, help="Use full image objects or not. They are huge and during debugging it is useful to turn off.") - group2.add_argument("--no-f","--no-full", action="store_true", default=False) - -args = parser.parse_args() - -debuglevel = 0 -if args.debug is None: - # -d was used but no value provided - debuglevel = 10 -elif args.debug: - debuglevel = args.debug - -full_images = args.full -single = args.single -output = args.output - +# FUNCTIONS def prn(*args,**kwargs): kwargs["end"] = "" print(*args,**kwargs) @@ -61,10 +33,12 @@ def serialize(item): eprint(f"WARNING: unknown type {type(item)} for json-serializing object {item}") return item -def html(checkouts, reservations): +def html(checkouts, reservations, imagepath, imagerelativepath): + """ + Make a pretty html page of the items. If imagepath and imagerelativepath are defined, save the images to imagepath, and set the html img tags src attribute to the imagerelativepath. + """ # Uses https://datatables.net/download/builder?dt/jq-3.7.0/dt-2.0.8/cr-2.0.3/fh-4.0.1 # with css corrected by having the utf-8 line at the top of the .min.css file. - """ Make an html of the items """ prn("\n") prn("\n") prn('\n') @@ -103,13 +77,27 @@ def html(checkouts, reservations): prn(f"{i['barcode']}") due = i["due"].strftime("%F") prn(f"{due}") + prn(f"{i['format']}") if "img" in i: img_src = i["img"] + if imagepath and imagerelativepath: + ext = i["img_type"].split("/")[-1] + img_contents = base64.b64decode(i["img"]) + # use chars -25 to -5 (so 20 characters long, 5 from the right end) + # to avoid the == at the end + # also img50 was annoying. + filename = f"{i['img'][-25:-5:]}.{ext}".replace("/","_") + filepath = os.path.join(imagepath, filename) + relativefilepath = os.path.join(imagerelativepath, filename) + with open(filepath,"wb") as w: + if debuglevel >= 3: + eprint(f"Writing to file {filepath} for {i['title']}") + w.write(img_contents) + prn(f"") + else: + prn(f"") else: - img_src = "" - #prn(f"{i['format']} ") - prn(f"{i['format']}") - prn(f"") + prn(f"none") prn(f"{i['title']}") prn(f"\n") prn(f"\n") @@ -157,6 +145,50 @@ def html(checkouts, reservations): """) prn(f"") +# ARGUMENTS +parser = argparse.ArgumentParser(description="Shows currently checked out items from the configured libraries.") +parser.add_argument("-d","--debug", nargs='?', default=0, type=int, choices=range(0,11), help="Set debug level. >=5 adds verbose=True to get_checkouts().") +# add output option: html, raw, json +# add mutual: all or single. +group1 = parser.add_mutually_exclusive_group() +group1.add_argument("-s","--single", help="Show this single account.") +group1.add_argument("-a","--all", action='store_true', default=True, help="Check all accounts") +parser.add_argument("-o","--output", choices=["html","json","raw"], default="raw", help="Output format.") +try: + # This was only added in python 3.9 + parser.add_argument("-f","--full", action=argparse.BooleanOptionalAction, default=True, help="Use full image objects or not. They are huge and during debugging it is useful to turn off.") +except AttributeError: + group2 = parser.add_mutually_exclusive_group() + group2.add_argument("-f","--full", action="store_true", default=True, help="Use full image objects or not. They are huge and during debugging it is useful to turn off.") + group2.add_argument("--no-f","--no-full", action="store_true", default=False) +parser.add_argument("-i","--imagepath", default=None, help="Affects html output only. Places images in this directory on the filesystem.") +parser.add_argument("-r","--imagerelativepath", default=None, help="Affects html output only. Use this relative path in the img src attribute. Required if -i is used.") + +args = parser.parse_args() + +# PARSE ARGUMENTS +debuglevel = 0 +if args.debug is None: + # -d was used but no value provided + debuglevel = 10 +elif args.debug: + debuglevel = args.debug + +full_images = args.full +single = args.single +output = args.output +imagepath = args.imagepath +imagerelativepath = args.imagerelativepath +# Both are required together. +if imagepath is not None and imagerelativepath is None: + eprint("Fatal! If --imagepath is used, you must also use --imagerelativepath") + sys.exit(1) + +if imagerelativepath is not None and imagepath is None: + eprint("Fatal! If --imagerelativepath is used, you must also use --imagepath") + sys.exit(1) + +# MAIN if "__main__" == __name__: if debuglevel >= 1: eprint(args) @@ -170,6 +202,6 @@ if "__main__" == __name__: elif "json" == output: print(json.dumps(checkouts,default=serialize)) elif "html" == output: - html(checkouts, reservations) + html(checkouts, reservations, imagepath, imagerelativepath) else: print(f"Error! Invalid choice for output format {output}.") -- cgit