From fb4c0af5fda76f40de9e1593daa72fc2c7287700 Mon Sep 17 00:00:00 2001 From: Dan Hamik Date: Mon, 25 Nov 2024 12:53:31 -0600 Subject: [PATCH] initial commit --- Dockerfile | 10 ++ crontab | 1 + libnotices.py | 281 +++++++++++++++++++++++++++++++++++++++++++++++ refresh.php | 13 +++ requirements.txt | 3 + 5 files changed, 308 insertions(+) create mode 100644 Dockerfile create mode 100644 crontab create mode 100644 libnotices.py create mode 100644 refresh.php create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9fcdd22 --- /dev/null +++ b/Dockerfile @@ -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/ diff --git a/crontab b/crontab new file mode 100644 index 0000000..b629e91 --- /dev/null +++ b/crontab @@ -0,0 +1 @@ +0 17 * * * python3 /usr/local/bin/libnotices.py \ No newline at end of file diff --git a/libnotices.py b/libnotices.py new file mode 100644 index 0000000..b9f9db0 --- /dev/null +++ b/libnotices.py @@ -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=""" + + + + +""" +tableend="
" + +returntable="Last Updated" + str(datetime.datetime.now()) +returntable+='
Click Here to be able to refresh the list.' +returntable+='
Click for the return list' +returntable += """
+ +
+""" + +#print(htmltable) +td="" +th="" +#returntable = 'Click to return to main list' +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 + 'Name'+ th +'Count' + for type in mediatypes: + typecount = sum(b.materialtype == type for b in duesoon) + if typecount>0: + returntable += "" + type + td + str(typecount) + "" + totalreturnbooks = len(duesoon) + returntable += "" + "Total" + td + str(totalreturnbooks) + "" + returntable += tableend + "
" + returntable += tablestart + "Name"+th+"Type"+th+"Times Renewed"+ th + "Renewal Status" + th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail" + for item in duesoon: + returntable += "" + 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 +'' +"\n" + returntable += tableend + "
" +returnlist = [d for d in allbooks if (d.renewalcount == 3)] +if len(returnlist) == 0: + pass +else: + returntable += tablestart + 'Name'+ th +'Count' + for type in mediatypes: + typecount = sum(b.materialtype == type for b in returnlist) + if typecount>0: + returntable += "" + type + td + str(typecount) + "" + totalreturnbooks = len(returnlist) + returntable += "" + "Total" + td + str(totalreturnbooks) + "" + returntable += tableend + "
" + returntable += tablestart + "Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail" + for item in returnlist: + returntable += "" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'' +"\n" +returnlist = [d for d in allbooks if (d.renewalcount == 2)] +if len(returnlist) == 0: + pass +else: + returntable += tablestart + 'Name'+ th +'Count' + for type in mediatypes: + typecount = sum(b.materialtype == type for b in returnlist) + if typecount>0: + returntable += "" + type + td + str(typecount) + "" + totalreturnbooks = len(returnlist) + returntable += "" + "Total" + td + str(totalreturnbooks) + "" + returntable += tableend + "
" + returntable += tablestart + "Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail" + for item in returnlist: + returntable += "" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'' +"\n" +returnlist = [d for d in allbooks if (d.renewalcount == 1)] +if len(returnlist) == 0: + pass +else: + returntable += tablestart + 'Name'+ th +'Count' + for type in mediatypes: + typecount = sum(b.materialtype == type for b in returnlist) + if typecount>0: + returntable += "" + type + td + str(typecount) + "" + totalreturnbooks = len(returnlist) + returntable += "" + "Total" + td + str(totalreturnbooks) + "" + returntable += tableend + "
" + returntable += tablestart + "Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail" + for item in returnlist: + returntable += "" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'' +"\n" +returnlist = [d for d in allbooks if (d.renewalcount == 0)] +if len(returnlist) == 0: + pass +else: + returntable += tablestart + 'Name'+ th +'Count' + for type in mediatypes: + typecount = sum(b.materialtype == type for b in returnlist) + if typecount>0: + returntable += "" + type + td + str(typecount) + "" + totalreturnbooks = len(returnlist) + returntable += "" + "Total" + td + str(totalreturnbooks) + "" + returntable += tableend + "
" + returntable += tablestart + "Name"+th+"Type"+th+"Times Renewed"+th+"Checked Out"+th+"Due Date"+th+"Title" + th + "ISBN" + th + "Thumbnail" + for item in returnlist: + returntable += "" + item.person + td + item.materialtype + td + str(item.renewalcount) + td + str(item.checkoutdate) + td + str(item.duedate) + td + item.title + td + item.isbn + td +'' +"\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() \ No newline at end of file diff --git a/refresh.php b/refresh.php new file mode 100644 index 0000000..ade15b4 --- /dev/null +++ b/refresh.php @@ -0,0 +1,13 @@ + + + Refreshing... + +

Refreshing...

+ + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3a0a771 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +boto==2.49.0 +boto3==1.26.27 +botocore==1.29.27 \ No newline at end of file