aboutsummaryrefslogtreecommitdiff
path: root/library_info_cli.py
diff options
context:
space:
mode:
Diffstat (limited to 'library_info_cli.py')
-rwxr-xr-xlibrary_info_cli.py133
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}.")
bgstack15