initial commit
This commit is contained in:
commit
fb4c0af5fd
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@ -0,0 +1,10 @@
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
RUN apt update && apt install cron apache2 python3 python3-pip -y
|
||||
COPY crontab /etc/cron.d/crontab
|
||||
COPY refresh.php /var/www/html/
|
||||
COPY libnotices.py /usr/local/bin/
|
||||
COPY requirements.txt /
|
||||
RUN pip3 install -r /requirements.txt
|
||||
RUN chmod +x /usr/local/bin/libnotices.py
|
||||
#COPY img/* /var/www/html/img/
|
281
libnotices.py
Normal file
281
libnotices.py
Normal file
@ -0,0 +1,281 @@
|
||||
import requests
|
||||
import datetime
|
||||
from tabulate import tabulate
|
||||
import boto3
|
||||
import json
|
||||
from json import JSONEncoder
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
class libaccount(dict):
|
||||
def __init__(self,name,barcode,pin):
|
||||
dict.__init__(self,name=name, barcode=barcode, pin=pin)
|
||||
self.name=name
|
||||
self.barcode=barcode
|
||||
self.pin=pin
|
||||
def toJson(self):
|
||||
return json.dumps(self,default=lambda o: o.__dict__)
|
||||
class book():
|
||||
def __init__(self,itemid,renewalcount,checkoutdate,duedate,vendor,resourceid,resourceinstanceid,title,materialtype,coverurl,person,authsession,renewresult,overdue,isbn):
|
||||
self.id=itemid
|
||||
self.renewalcount=renewalcount
|
||||
self.checkoutdate=checkoutdate
|
||||
self.duedate=duedate
|
||||
self.vendor=vendor
|
||||
self.resourceid=resourceid
|
||||
self.resourceinstanceid=resourceinstanceid
|
||||
self.title=title
|
||||
self.materialtype=materialtype
|
||||
self.coverurl=coverurl
|
||||
self.person=person
|
||||
self.authsession=authsession
|
||||
self.renewresult=renewresult
|
||||
self.overdue=overdue
|
||||
self.isbn=isbn
|
||||
#self.ill=ill
|
||||
def print(self):
|
||||
print(self.person, self.id, self.title, self.checkoutdate, self.renewalcount, self.duedate, self.materialtype,self.renewresult, self.isbn)
|
||||
def renew(self):
|
||||
try:
|
||||
logging.info("Renewing Book",self.title)
|
||||
renewuri='https://na2.iiivega.com/api/search-result/patrons/me/checkouts/' + self.id + '/renew'
|
||||
try:
|
||||
renewresult = self.authsession.post(renewuri).json()
|
||||
if renewresult.get('message'):
|
||||
self.renewresult=renewresult['message']
|
||||
else:
|
||||
self.renewalcount=renewresult['renewalCount']
|
||||
self.duedate=renewresult['dueDate']
|
||||
self.renewresult="Successfully Renewed"
|
||||
except requests.exceptions.RequestException as e: # This is the correct syntax
|
||||
logging.error(e.json())
|
||||
finally:
|
||||
pass
|
||||
#print(renewresult.json())
|
||||
except Exception as ex:
|
||||
logging.error(ex)
|
||||
def sendemail(body,subject):
|
||||
logging.info("Sending Email")
|
||||
boto3.setup_default_session(profile_name='default')
|
||||
sesclient=boto3.client('ses',region_name="us-east-2")
|
||||
CHARSET="UTF-8"
|
||||
response = sesclient.send_email(
|
||||
Destination={
|
||||
"ToAddresses":recipients
|
||||
},
|
||||
Message= {
|
||||
"Body": {
|
||||
"Html": {
|
||||
"Charset": CHARSET,
|
||||
"Data": body
|
||||
}
|
||||
},
|
||||
"Subject": {
|
||||
"Charset": CHARSET,
|
||||
"Data": subject
|
||||
},
|
||||
},
|
||||
Source='librarynotices@hamik.net'
|
||||
)
|
||||
upcomingdays=5
|
||||
autorenewaldays=3
|
||||
alwayssendemail=False
|
||||
returndata=False
|
||||
recipients=['dan@hamik.net','allisonmhamik@gmail.com','danalli@hamik.net','henryhamik@gmail.com','charleyhamik@gmail.com']
|
||||
uri = "https://auth.na2.iiivega.com/auth/realms/sioux/protocol/openid-connect/token"
|
||||
checkoutsuri='https://sioux.na2.iiivega.com/api/search-result/patrons/me/checkouts'
|
||||
with open('/var/www/data/libaccounts.json') as accountfile:
|
||||
accountsjson= json.load(accountfile)
|
||||
|
||||
accounts=[]
|
||||
for account in accountsjson:
|
||||
accounts.append(
|
||||
libaccount(
|
||||
accountsjson[account]['name'],
|
||||
str(accountsjson[account]['barcode']),
|
||||
str(accountsjson[account]['pin']))
|
||||
)
|
||||
|
||||
allbooks=[]
|
||||
mediatypes=[]
|
||||
for myaccount in accounts:
|
||||
account=myaccount
|
||||
logging.info(account['name'])
|
||||
# Create a session
|
||||
session = requests.Session()
|
||||
authbody = {
|
||||
'username':account.barcode,
|
||||
'password':account.pin,
|
||||
'client_id':'convergence',
|
||||
'grant_type':'password',
|
||||
}
|
||||
resp=session.post(uri,authbody).json()
|
||||
authtoken=resp['access_token']
|
||||
tokentype=resp['token_type']
|
||||
sessionstate=resp['session_state']
|
||||
|
||||
session.headers.update({
|
||||
'iii-customer-domain':'sioux.na2.iiivega.com',
|
||||
'Origin':'https://sioux.na2.iiivega.com/',
|
||||
'Referrer':'https://sioux.na2.iiivega.com/',
|
||||
'access_token':authtoken,
|
||||
'Authorization':'Bearer ' + authtoken,
|
||||
'token_type': tokentype,
|
||||
'session_state': sessionstate,
|
||||
'api-version':'1',
|
||||
'DNT':'1',
|
||||
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'
|
||||
} )
|
||||
outs = session.get(checkoutsuri)
|
||||
if len(outs.json()) >=1:
|
||||
for mybook in outs.json():
|
||||
if mybook['vendor']=='overdrive':
|
||||
continue
|
||||
if mybook['vendor']=='hoopla':
|
||||
continue
|
||||
try:
|
||||
myisbn = mybook['resource']['coverUrl']['small'].split('=')[1].split("/")[0]
|
||||
except:
|
||||
myisbn=''
|
||||
duedate = datetime.datetime.strptime(mybook['dueDate'].split('T')[0],'%Y-%m-%d').date()
|
||||
if datetime.date.today() > duedate:
|
||||
overdue=True
|
||||
else:
|
||||
overdue = False
|
||||
try:
|
||||
thisbook = book(
|
||||
mybook['id'],
|
||||
mybook['renewalCount'],
|
||||
datetime.datetime.strptime(mybook['checkOutDate'].split('T')[0],'%Y-%m-%d').date(),
|
||||
duedate,
|
||||
mybook['vendor'],
|
||||
mybook['resource']['id'],
|
||||
mybook['resource']['instanceId'],
|
||||
mybook['resource']['title'],
|
||||
mybook['resource']['materialType'],
|
||||
mybook['resource']['coverUrl']['small'],
|
||||
account.name,
|
||||
session,
|
||||
'None',
|
||||
overdue,
|
||||
myisbn
|
||||
)
|
||||
if thisbook.materialtype in mediatypes:
|
||||
pass
|
||||
else:
|
||||
mediatypes.append(thisbook.materialtype)
|
||||
except Exception as e:
|
||||
print(e,mybook)
|
||||
|
||||
allbooks.append(thisbook)
|
||||
for book in allbooks:
|
||||
#print(datetime.date.today(),book.duedate)
|
||||
if datetime.date.today() > book.duedate:
|
||||
book.renew()
|
||||
|
||||
#sendemail()
|
||||
tablestart="""
|
||||
<!DOCTYPE html PUBLIC "-=//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns=3D"http://www.w3.org/1999/xhtml">
|
||||
<head> </head>
|
||||
<body>
|
||||
<style>
|
||||
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
|
||||
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
|
||||
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
|
||||
</style><table>"""
|
||||
tableend="</table> </body></html>"
|
||||
|
||||
returntable="Last Updated" + str(datetime.datetime.now())
|
||||
returntable+='<br>Click <a href="https://librarynotice.hamik.net">Here</a> to be able to refresh the list.'
|
||||
returntable+='<br>Click for the <a href="https://librarynotice.hamik.net/returnlist.html">return list</a>'
|
||||
returntable += """<form action="https://librarynotice.hamik.net/refresh.php">
|
||||
<input type="submit" value="Refresh Items">
|
||||
</form>
|
||||
"""
|
||||
|
||||
#print(htmltable)
|
||||
td="</td><td>"
|
||||
th="</th><th>"
|
||||
#returntable = '<a href="https://librarynotice.hamik.net">Click to return to main list</a>'
|
||||
duesoon = [d for d in allbooks if (d.duedate < datetime.date.today() + datetime.timedelta(days=10)) and not (str(d.renewresult).lower() == 'None'.lower())]
|
||||
if len(duesoon) >=1:
|
||||
returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
|
||||
for type in mediatypes:
|
||||
typecount = sum(b.materialtype == type for b in duesoon)
|
||||
if typecount>0:
|
||||
returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
|
||||
totalreturnbooks = len(duesoon)
|
||||
returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"
|
||||
returntable += tableend + "<br>"
|
||||
returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+ th + "Renewal Status" + th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
|
||||
for item in duesoon:
|
||||
returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.renewresult)+ td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
|
||||
returntable += tableend + "<BR>"
|
||||
returnlist = [d for d in allbooks if (d.renewalcount == 3)]
|
||||
if len(returnlist) == 0:
|
||||
pass
|
||||
else:
|
||||
returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
|
||||
for type in mediatypes:
|
||||
typecount = sum(b.materialtype == type for b in returnlist)
|
||||
if typecount>0:
|
||||
returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
|
||||
totalreturnbooks = len(returnlist)
|
||||
returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"
|
||||
returntable += tableend + "<br>"
|
||||
returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
|
||||
for item in returnlist:
|
||||
returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
|
||||
returnlist = [d for d in allbooks if (d.renewalcount == 2)]
|
||||
if len(returnlist) == 0:
|
||||
pass
|
||||
else:
|
||||
returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
|
||||
for type in mediatypes:
|
||||
typecount = sum(b.materialtype == type for b in returnlist)
|
||||
if typecount>0:
|
||||
returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
|
||||
totalreturnbooks = len(returnlist)
|
||||
returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"
|
||||
returntable += tableend + "<br>"
|
||||
returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
|
||||
for item in returnlist:
|
||||
returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
|
||||
returnlist = [d for d in allbooks if (d.renewalcount == 1)]
|
||||
if len(returnlist) == 0:
|
||||
pass
|
||||
else:
|
||||
returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
|
||||
for type in mediatypes:
|
||||
typecount = sum(b.materialtype == type for b in returnlist)
|
||||
if typecount>0:
|
||||
returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
|
||||
totalreturnbooks = len(returnlist)
|
||||
returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"
|
||||
returntable += tableend + "<br>"
|
||||
returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
|
||||
for item in returnlist:
|
||||
returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
|
||||
returnlist = [d for d in allbooks if (d.renewalcount == 0)]
|
||||
if len(returnlist) == 0:
|
||||
pass
|
||||
else:
|
||||
returntable += tablestart + '<colgroup><col/><col/></colgroup><tr><th>Name'+ th +'Count</th></tr>'
|
||||
for type in mediatypes:
|
||||
typecount = sum(b.materialtype == type for b in returnlist)
|
||||
if typecount>0:
|
||||
returntable += "<tr><td>" + type + td + str(typecount) + "</td></tr>"
|
||||
totalreturnbooks = len(returnlist)
|
||||
returntable += "<tr><td><b>" + "Total" + td + str(totalreturnbooks) + "</b></td></tr>"
|
||||
returntable += tableend + "<br>"
|
||||
returntable += tablestart + "<colgroup><col/><col/><col/><col/><col/><col/><col/><col/></colgroup><tr><th>Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail</th></tr>"
|
||||
for item in returnlist:
|
||||
returntable += "<TR><TD>" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'<img src="'+ item.coverurl+'">' +"</td></tr>\n"
|
||||
with open("/var/www/html/returnlist.html","w",encoding='utf-8') as outhtml:
|
||||
outhtml.write(returntable)
|
||||
htmltable = returntable
|
||||
with open("/var/www/html/index.html","w",encoding='utf-8') as outhtml:
|
||||
outhtml.write(htmltable)
|
||||
sendemail(htmltable,"Checked Out Library Books Report " + str(datetime.date.today()))
|
||||
#for item in duesoon:
|
||||
# item.print()
|
13
refresh.php
Normal file
13
refresh.php
Normal file
@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title> Refreshing...</title>
|
||||
</head>
|
||||
<body> <h2>Refreshing...</h2>
|
||||
<?php
|
||||
ob_start();
|
||||
print "Refreshing...";
|
||||
ob_flush();
|
||||
shell_exec("python3 /usr/local/bin/libnotices.py");
|
||||
header('Location: /');
|
||||
?>
|
||||
</body></html>
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
boto==2.49.0
|
||||
boto3==1.26.27
|
||||
botocore==1.29.27
|
Loading…
x
Reference in New Issue
Block a user