aboutsummaryrefslogtreecommitdiff
path: root/libraries/aspen.py
blob: 1d8de398e17ed9c74e3356a88b63aaba25e3aef8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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