aboutsummaryrefslogtreecommitdiff
path: root/libraries/aspen.py
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/aspen.py')
-rw-r--r--libraries/aspen.py125
1 files changed, 125 insertions, 0 deletions
diff --git a/libraries/aspen.py b/libraries/aspen.py
new file mode 100644
index 0000000..1d8de39
--- /dev/null
+++ b/libraries/aspen.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+# File: libraries/aspen.py
+# Author: bgstack15
+# Startdate: 2024-07-06-7 08:06
+# SPDX-License-Identifier: GPL-3.0-only
+# Title: Library Plugin for Aspen
+# Project: library_info
+# Purpose: plugin for aspen-based library websites
+# History:
+# Usage:
+# Reference:
+# Improve:
+# Dependencies:
+# dep-devuan: python3-bs4
+
+from .base import *
+import requests, json, dateutil, base64, os, sys
+from bs4 import BeautifulSoup
+
+class Library(BaseLibrary):
+
+ def __init__(self, config_obj = None, alias = None, username = None, password = None, baseurl = None, session = None):
+ if config_obj and "username" in config_obj:
+ self.username = config_obj["username"]
+ else:
+ self.username = username
+ if config_obj and "password" in config_obj:
+ self.password = config_obj["password"]
+ else:
+ self.password = password
+ if config_obj and "baseurl" in config_obj:
+ self.baseurl = config_obj["baseurl"]
+ else:
+ self.baseurl = baseurl if baseurl else "https://aspen.example.org"
+ self.baseurl = self.baseurl.rstrip("/")
+ if session and type(session) == requests.sessions.Session:
+ self.session = session
+ else:
+ self.session = requests.Session()
+ if config_obj and "alias" in config_obj:
+ self.alias = config_obj["alias"]
+ else:
+ self.alias = alias if alias else "Aspen-based library"
+ # log in now. Why would we not?
+ self.login()
+
+ def get_checkouts(self, verbose = False):
+ # WORKHERE: no example of possible/completed renewals at this time
+ checked_out_objects = []
+ b = self.baseurl
+ s = self.session
+ # step 1: visit the "checked out" web page, so it doesn't freak out that I am taking shortcuts
+ headers = {
+ "Content-Type": "application/x-www-form-urlencoded",
+ "Referer": f"{b}/MyAccount/Home",
+ "Priority": "u=1"
+ }
+ s.get(f"{b}/MyAccount/CheckedOut", headers = headers)
+ # step 2: visit the checkout list which is a cruddy html-inside-json garbage
+ headers = {
+ "Referer": f"{b}/MyAccount/CheckedOut?source=all"
+ }
+ params = {
+ "method": "getCheckouts",
+ "source": "all"
+ }
+ output = s.get(f"{b}/MyAccount/AJAX",params=params,headers=headers)
+ output = json.loads(output.content)["checkouts"].replace("\xa0"," ")
+ soup = BeautifulSoup(output, "html.parser")
+ # goals: get title, format, picture, barcode, due date, possible renewal date, times_renewed, when_checked_out
+ results = soup.find_all("div", class_ = "result row")
+ #results = soup.find_all("span",class_="result-index")
+ #results = [i.parent.parent.parent for i in results]
+ for i in results:
+ title = i.find(class_ = "result-title").contents[0]
+ labels = [j.contents[0] for j in i.find_all("div", class_ = "result-label")]
+ values = [j.contents[0] for j in i.find_all("div", class_ = "result-value")]
+ values_dict = dict(map(lambda i,j:(i,j),labels,values))
+ if verbose:
+ print(f"DEBUG: Values_dict: {values_dict}",file=sys.stderr)
+ # contains Call number, Format, Barcode, Due
+ img_href = i.find("img", class_="listResultImage")["src"]
+ img_response = s.get(img_href)
+ img_b64 = base64.b64encode(img_response.content).decode()
+ img_type = img_response.headers["Content-Type"]
+ # normalize format
+ item_format = ""
+ item_format = "book" if "book" in values_dict["Format"].lower() else ""
+ if not item_format:
+ item_format = values_dict["Format"]
+ obj = {
+ "patron": self.alias,
+ "title": title,
+ "format": item_format,
+ "barcode": values_dict["Barcode"],
+ "due": dateutil.parser.parse(values_dict["Due"]),
+ "img_href": img_href,
+ "img50": img_b64[:50],
+ "img": img_b64,
+ "img_type": img_type,
+ }
+ checked_out_objects.append(obj)
+ return checked_out_objects
+
+ def get_class_name(self):
+ return os.path.basename(__file__).replace(".py","")
+
+ def login(self):
+ b = self.baseurl
+ s = self.session
+ # step 1: visit login page
+ s.get(f"{b}/MyAccount/Home")
+ # step 2: log in
+ # curl 'https://aspen.example.org/MyAccount/Home' -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Referer: https://aspen.example.org/MyAccount/Home' -H 'Priority: u=1' --data-raw 'username=987213497234&password=1234&submit=Login'
+ data = {
+ "username": self.username,
+ "password": self.password,
+ "submit": "Login"
+ }
+ headers = {
+ "Content-Type": "application/x-www-form-urlencoded",
+ "Referer": f"{b}/MyAccount/Home",
+ "Priority": "u=1"
+ }
+ s.post(f"{b}/MyAccount/Home", headers = headers, data = data)
bgstack15