diff options
Diffstat (limited to 'library_info_cli.py')
-rwxr-xr-x | library_info_cli.py | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/library_info_cli.py b/library_info_cli.py new file mode 100755 index 0000000..49a3b5d --- /dev/null +++ b/library_info_cli.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# File: library_info_cli.py +# Author: bgstack15 +# Startdate: 2024-07-06-7 15:19 +# Title: CLI for library_info +# Project: library_info +# Purpose: cli client for library_info_lib +# History: +# Usage: --help +# Reference: +# Improve: +# Dependencies: + +import argparse, sys, json, datetime +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.") +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.") + +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 + +def prn(*args,**kwargs): + kwargs["end"] = "" + print(*args,**kwargs) + +def eprint(*args,**kwargs): + kwargs["file"] = sys.stderr + print(*args,**kwargs) + +def serialize(item): + eprint(f"DEBUG: trying to serialize {item}, type {type(item)}") + if type(item) == datetime.datetime: + # We know library due dates are just a day, and not a time. + return item.strftime("%F") + else: + eprint(f"WARNING: unknown type {type(item)} for json-serializing object {item}") + return item + +def html(items): + # 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("<html>\n") + prn("<head>\n") + prn('<meta name="viewport" content="width=device-width, initial-scale=1">\n') + prn('<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">\n') + prn('<link href="DataTables/datatables.min.css" rel="stylesheet">\n') + prn('<link rel=stylesheet type="text/css" href="library.css">') + # inline css, if any + prn('<style type="text/css">\n') + prn('</style>\n') + prn("<title>Library checkouts</title>\n") + prn("</head>\n") + prn("<body>\n") + seen_accounts = [] + for i in items: + if i["patron"] not in seen_accounts: + seen_accounts.append(i["patron"]) + if seen_accounts: + prn("<h2>Accounts: ") + prn(", ".join(seen_accounts)) + prn("</h2>\n") + prn("<span class='eighty'>Last modified: " + datetime.datetime.now(datetime.UTC).strftime("%FT%TZ") + "</span>\n") + if len(items): + prn("<table class='display' id='checkouts'>\n") + prn(f"<thead><tr><th>Patron</th><th>barcode</th><th>due</th><th>format</th><th>cover</th><th>Title</th></tr></thead>\n") + prn("<tbody>\n") + for i in items: + prn(f"<tr>") + prn(f"<td>{i['patron']}</td>") + prn(f"<td>{i['barcode']}</td>") + due = i["due"].strftime("%F") + prn(f"<td>{due}</td>") + if "img" in i: + img_src = i["img"] + else: + img_src = "" + #prn(f"<td>{i['format']} <img class='thumb' src='data:image/png;base64, {img_src}' /><span><img class='full' src='data:image/png;base64, {img_src}' /></span></td>") + prn(f"<td>{i['format']}</td>") + prn(f"<td><img class='thumb' src='data:{i['img_type']};base64, {img_src}' /></td>") + prn(f"<td>{i['title']}</td>") + prn(f"</tr>\n") + prn(f"</tbody>\n") + prn(f"</table>\n") + prn(f"</body>\n") + prn(f"<footer>\n") + prn(f"</footer>\n") + prn('<script src="DataTables/datatables.min.js"></script>') + # disable paging, because I dislike it. + # Use column 2 (due date) ascending as initial sort. + prn(""" +<script>$(document).ready( + function () { + var table = $('#checkouts').DataTable({paging: false}); + table.column('2:visible').order('asc').draw(); + } +);</script> +""") + prn(f"</html>") + +if "__main__" == __name__: + if debuglevel >= 1: + eprint(args) + if single: + items = library_info_lib.get_single_checkouts(alias = single, full_images = full_images, verbose = debuglevel >= 5) + else: + items = library_info_lib.get_all_checkouts(full_images = full_images, verbose = debuglevel >= 5) + if "raw" == output: + print(items) + elif "json" == output: + print(json.dumps(items,default=serialize)) + elif "html" == output: + html(items) + else: + print(f"Error! Invalid choice for output format {output}.") |