Compare commits

...

9 Commits

Author SHA1 Message Date
giuliof 9819fbdead Merge pull request 'Merge dev/remoteFetch' (#2) from dev/remoteFetch into master
Reviewed-on: #2
2021-09-14 19:41:11 +00:00
giuliof d6f476167d Testato, aggiunta libreria logger.
- Logging in conf/tpdf.log anziché in std{out,err}.
- Fix di alcune conversioni.
- TODO: spostare la posizione del logfile e del loglevel nel conf.ini.
2021-09-04 11:22:00 +02:00
giuliof 6c20ea6d0f Handled value error 2021-09-04 11:20:53 +02:00
giuliof df82337f1f Proper way to handle logging of exceptions 2021-09-04 11:15:26 +02:00
giuliof 34dbffac9f fatal->error 2021-09-04 11:04:07 +02:00
giuliof 54bbdb919e Write a string 2021-09-04 11:00:37 +02:00
giuliof cd6543f837 Rimosso encoding 2021-09-04 10:50:11 +02:00
giuliof 45752d2903 Test con la libreria di logging 2021-09-04 10:45:51 +02:00
giuliof e5143a86ad Tentativo di implementazione fetching remoto .tc. Da testare
- Richiesta HTTP (o via webdav, è equivalente).
- Uso del Last-modified nell'header HTTP per il rinnovo della cache.
2021-09-04 00:21:56 +02:00
2 changed files with 98 additions and 51 deletions

View File

@ -9,7 +9,9 @@
[default] [default]
# Path to Tellico .tc database to use # Path to Tellico .tc database to use
path = /path/to/some/tellico.tc path = http://path/to/some/tellico.tc
user = user
pswd = pswd
# Path to output directory for images and temporary data # Path to output directory for images and temporary data
# Must be accessible by webserver # Must be accessible by webserver

145
main.py
View File

@ -20,65 +20,110 @@ import json
import sys import sys
import cgitb, cgi import cgitb, cgi
import zipfile import zipfile
from io import BytesIO
import shutil as sh import shutil as sh
import os import os
import time import time
import logging
# Connection to remote library file
import requests
# Parsing of HTTP RFC 1123 datetime format
from email.utils import parsedate_to_datetime
# Our custom library (again no pun intended) # Our custom library (again no pun intended)
import tcparser import tcparser
# Global variables and configurations
import glob import glob
# Start CGI handling for webserver
cgitb.enable()
inputvars = cgi.FieldStorage()
print('Content-Type: text/json; charset=utf-8')
print('Access-Control-Allow-Origin: *')
print()
### End of HTTP headers: it is now safe to output things
##########################################################
# Create output directory and temporary files if they do not exist
if not os.path.exists(glob.conf['default']['outdir']):
os.mkdir(glob.conf['default']['outdir'])
if not os.path.exists(glob.conf['default']['outdir'] + '/lastupdate.txt'):
luh = open(glob.conf['default']['outdir'] + '/lastupdate.txt', 'w')
luh.write('0')
luh.close()
# Retrieve last database update timestamp
luh = open(glob.conf['default']['outdir'] + '/lastupdate.txt', 'r')
lu = int(float(luh.read()))
luh.close()
mtime = os.path.getmtime(glob.conf['default']['path'])
if int(lu) < int(mtime):
# Unzip Tellico .tc database
zipHandler = zipfile.ZipFile(glob.conf['default']['path'], 'r')
zipHandler.extractall(glob.conf['default']['outdir'])
zipHandler.close()
luh = open(glob.conf['default']['outdir'] + '/lastupdate.txt', 'w')
luh.write(str(time.time()))
luh.close()
# Get a Python-friendly library struct from XML file
library = tcparser.getLibrary(glob.conf['default']['outdir'] + "/tellico.xml", lu)
### Get filters to search for books ###
try: try:
title = inputvars['title'].value
except KeyError:
title = ''
try: # Start the logging library (to avoid printing on stdout)
author = inputvars['author'].value # TODO
except KeyError: logging.basicConfig(filename='conf/tpdf.log', level=logging.DEBUG)
author = ''
# Start CGI handling for webserver
cgitb.enable()
inputvars = cgi.FieldStorage()
logging.debug("Started CGI")
print('Content-Type: text/json; charset=utf-8')
print('Access-Control-Allow-Origin: *')
print()
### End of HTTP headers: it is now safe to output things
##########################################################
# Create output directory and temporary files if they do not exist
if not os.path.exists(glob.conf['default']['outdir']):
logging.debug("missing outdir, creating...")
os.mkdir(glob.conf['default']['outdir'])
if not os.path.exists(glob.conf['default']['outdir'] + '/lastupdate.txt'):
logging.debug("missing lastupdate.txt, creating...")
luh = open(glob.conf['default']['outdir'] + '/lastupdate.txt', 'w')
luh.write('0')
luh.close()
# Retrieve last database update timestamp
luh = open(glob.conf['default']['outdir'] + '/lastupdate.txt', 'r')
try:
lu = int(float(luh.read()))
except ValueError:
lu = 0
luh.close()
logging.info("last database update timestamp is %d" % lu)
result = tcparser.filter(library, title=title, author=author) # Fetch last modified from HTTP header
path = glob.conf['default']['path']
user = glob.conf['default']['user']
pswd = glob.conf['default']['pswd']
req = requests.head(path, auth=(user, pswd))
# Wanna get a pretty JSON encoded library to do your nasty things offline at home? ;-) logging.debug("fetched header from %s, returned code %d" % (path, req.status_code))
print(json.dumps(result, indent=4))
cachefile = glob.conf['default']['outdir'] + "/tellico.xml"
# If header fetch fails I can't update cache.
# Try with current one, if exists
if req.status_code == 200 and 'Last-modified' in req.headers:
mtime = int(parsedate_to_datetime(req.headers['Last-modified']).timestamp())
logging.info("Tellico last modified timestamp is %d" % mtime)
# If local xml is out-of-date or missing, try download it
if int(lu) < int(mtime) or not os.path.isfile(cachefile):
logging.info("Out-of-date, updating")
# Download Tellico .tc database
req = requests.get(path, auth=(user, pswd))
if req.status_code == 200 and req.content != None:
# Unzip Tellico .tc database and "cache it" locally
zipHandler = zipfile.ZipFile(BytesIO(req.content), 'r')
zipHandler.extractall(glob.conf['default']['outdir'])
zipHandler.close()
luh = open(glob.conf['default']['outdir'] + '/lastupdate.txt', 'w')
luh.write(str(mtime))
luh.close()
else:
logging.error("Update failed")
# Get a Python-friendly library struct from XML file
library = tcparser.getLibrary(cachefile, lu)
### Get filters to search for books ###
try:
title = inputvars['title'].value
except KeyError:
title = ''
try:
author = inputvars['author'].value
except KeyError:
author = ''
result = tcparser.filter(library, title=title, author=author)
# Wanna get a pretty JSON encoded library to do your nasty things offline at home? ;-)
print(json.dumps(result, indent=4))
# Avoid printing on str{out,err} the unexpected exception traces. Log it instead.
except Exception as e:
logging.exception(e)