diff options
author | B. Stack <bgstack15@gmail.com> | 2024-07-09 15:11:26 -0400 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2024-07-09 15:11:26 -0400 |
commit | 516263ea51350514571deafc70b14f9f19d760d8 (patch) | |
tree | 9da665d2e3eee383335c5f2ecc82dd649824ed66 /libraries/aspen.py | |
download | library-info-516263ea51350514571deafc70b14f9f19d760d8.tar.gz library-info-516263ea51350514571deafc70b14f9f19d760d8.tar.bz2 library-info-516263ea51350514571deafc70b14f9f19d760d8.zip |
initial commit
Diffstat (limited to 'libraries/aspen.py')
-rw-r--r-- | libraries/aspen.py | 125 |
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) |