Varia library working group XPPL. https://gitea.xpub.nl/XPUB/XPPL
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1246 lines
36 KiB

import codecs
import datetime
import io
import json
import os
from csv import DictReader, DictWriter
from functools import wraps
from urllib.parse import quote as urlquote
import autocomplete
from flask import Response, abort
from flask import current_app as app
from flask import (
flash, jsonify, redirect, render_template, request, send_from_directory,
url_for
)
from flask_socketio import emit
from flask_weasyprint import HTML, render_pdf
from sqlalchemy.inspection import inspect
from sqlalchemy.sql.expression import func
from werkzeug.utils import secure_filename
from xppl.cover import get_cover
from xppl.database import db
from xppl.extractText import extract_text
from xppl.forms import (
AddtoStackForm, EditForm, EditStackForm, SearchForm, StackForm, UploadForm
)
from xppl.getannot import get_annot_book, get_annot_results, get_annotations
from xppl.models import (
Author, AuthorSchema, Book, BookSchema, Chat, ChatSchema, Instance,
Potential, Stack, StackSchema, UserIns
)
from xppl.socketio import socketio
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'chm', 'mobi'])
author_schema = AuthorSchema()
authors_schema = AuthorSchema(many=True)
book_schema = BookSchema()
books_schema = BookSchema(many=True)
stack_schema = StackSchema()
stacks_schema = StackSchema(many=True)
chat_schema = ChatSchema()
chats_schema = ChatSchema(many=True)
def allowed_file(filename):
extension = filename.rsplit('.', 1)[1].lower()
return '.' in filename and extension in ALLOWED_EXTENSIONS
###
# Routing for your application.
###
def check_light(func):
@wraps(func)
def decorated_function(*args, **kwargs):
if not app.config['LIGHT']:
return func(*args, **kwargs)
else:
flash("Your account has expired. Update your billing info.")
return redirect(url_for('home'))
return decorated_function
@app.route('/', methods=['POST', 'GET'])
def home():
chat_messages = db.session.query(Chat).all()
username = 'librarian'
server = request.host
if request.environ.get('HTTP_X_FORWARDED_FOR') is None:
client = request.environ['REMOTE_ADDR']
else:
client = request.environ['HTTP_X_FORWARDED_FOR']
return render_template(
'home.html',
domain=app.config['DOMAIN'],
chat=chat_messages,
channel=1,
username=username,
client=client,
server=server,
light=app.config['LIGHT'],
)
@app.route('/about/')
def about():
"""Render the website's about page."""
return render_template('about.html', light=app.config['LIGHT'])
@app.route('/uploads/<filename>')
@check_light
def uploaded_file(filename):
book = Book.query.filter_by(file=filename).first()
i = Instance(request.host, "download")
existing_ip = db.session.query(Instance).filter_by(ip=request.host).first()
if existing_ip:
i.name = existing_ip.name
book.instances.append(i)
db.session.commit()
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
# annotations
@app.route('/annotations')
def annotations():
"""Render annotations page."""
books = db.session.query(Book).all()
annot = get_annotations()
return render_template(
'annotations.html',
annot=annot,
books=books,
light=app.config['LIGHT']
)
# PDF from annotations
@app.route('/annotations.pdf')
def annotations_pdf():
annot = get_annotations()
# Make a PDF straight from HTML in a string.
html = render_template(
'annotations.html',
annot=annot,
light=app.config['LIGHT'],
)
return render_pdf(HTML(string=html))
@app.route('/viewpdf/<filename>')
def viewtestfile1_file(filename):
return redirect((
"/static/viewer/web/viewer.html?file=%2Fuploads%2F"
+
urlquote(filename)
))
@app.route('/cover/<filename>')
def uploaded_file_cover(filename):
return send_from_directory(app.config['UPLOAD_FOLDER_COVER'],
filename)
@app.route('/updates', methods=['POST', 'GET'])
def get_updates():
allbooks = db.session.query(Book).all()
scrolling_message = (
'{domain} ~ XPPL ~ Updates'
' / / / / / / / '
'{count} books online '
).format(
domain=app.config['DOMAIN'],
count=str(len(allbooks))
)
userin = UserIns.query.filter_by(title='lastViewed').first()
if userin:
scrolling_message += (
' / / / / / / / '
' Last viewed: {user}'
).format(user=userin.info)
if allbooks:
latest_upload = allbooks[-1]
scrolling_message += (
' / / / / / / / '
'Latest entry: {title}'
).format(title=latest_upload.title)
return scrolling_message
@app.route('/volumetric_catalog', methods=['GET'])
def volumetric_catalog():
return render_template('volumetric_catalog/index.html')
@app.route('/scape', methods=['POST', 'GET'])
def scape():
if request.method == 'POST':
data = request.form
book = Book.query.get(data['id'])
book.scapeX = data['x']
book.scapeY = data['y']
db.session.commit()
books = db.session.query(Book).all()
all_instances = db.session.query(Instance).all()
instances = []
for instance in all_instances:
exists = False
for existing_inst in instances:
if existing_inst.name == instance.name:
exists = True
break
else:
exists = False
if not exists:
instances.append(instance)
return render_template('scape.html', books=books, instances=instances)
@app.route('/scape_new', methods=['POST', 'GET'])
def scape_new():
return render_template('scape_new.html')
@app.route('/books_grid')
def show_books_grid():
books = db.session.query(Book).all()
return render_template(
'show_books_grid.html',
books=books,
light=app.config['LIGHT']
)
@app.route('/books/<int:id>')
def show_book_by_id(id):
book = Book.query.get(id)
all_instances = db.session.query(Instance).all()
previousbook = Book.query.filter_by(id=id - 1).first()
nextbook = Book.query.filter_by(id=id + 1).first()
allbooks = db.session.query(Book).all()
edge = len(allbooks)
if id == 1:
previousbook = None
if id == edge:
nextbook = None
name = book.file
annot = get_annotations()
res = get_annot_book(annot, name)
userin = UserIns.query.filter_by(title="lastViewed").first()
if userin is not None:
userin.info = book.title
db.session.commit()
else:
user_info = UserIns("lastViewed", book.title)
db.session.add(user_info)
db.session.commit()
if not book:
return render_template(
'red_link.html',
id=id,
light=app.config['LIGHT']
)
else:
return render_template(
'show_book_detail.html',
book=book,
previousbook=previousbook,
nextbook=nextbook,
all_instances=all_instances,
name=name,
annot=annot,
res=res,
light=app.config['LIGHT']
)
@app.route('/books/<int:id>/delete', methods=['POST', 'GET'])
@check_light
def remove_book_by_id(id):
book_to_edit = Book.query.filter_by(id=id).first()
title = book_to_edit.title
Book.query.filter_by(id=id).delete()
db.session.commit()
flash("%s deleted from library" % (title))
return redirect(url_for('show_books'))
@app.route('/books/<int:id>/edit', methods=['POST', 'GET'])
@check_light
def edit_book_by_id(id):
book_to_edit = Book.query.filter_by(id=id).first()
user_form = EditForm(
title=book_to_edit.title,
author=book_to_edit.authors,
category=book_to_edit.category,
year_published=book_to_edit.year_published,
message=book_to_edit.message,
sameness=book_to_edit.sameness,
gender=book_to_edit.gender,
diversity=book_to_edit.diversity,
who=book_to_edit.who
)
if request.method == 'POST':
if user_form.validate_on_submit():
title = user_form.title.data
input_authors = user_form.author.data
category = user_form.category.data
year_published = user_form.year_published.data
message = user_form.message.data
sameness = user_form.sameness.data
gender = user_form.gender.data
diversity = user_form.diversity.data
who = user_form.who.data
if year_published == "":
year_published = None
book = Book.query.filter_by(id=id).first()
book.title = title
book.category = category
book.year_published = year_published
book.message = message
book.sameness = sameness
book.gender = gender
book.diversity = diversity
book.who = who
book.authors.clear()
for i, author in enumerate(input_authors):
author_name = author.get("author_name")
if author_name:
a = (
db.session.query(Author)
.filter_by(author_name=author_name).first()
)
if a is None:
a = Author(author_name=author_name)
db.session.add(a)
book.authors.append(a)
i = Instance(request.host, "edit")
existing_ip = (
db.session.query(Instance)
.filter_by(ip=request.host).first()
)
if existing_ip:
i.name = existing_ip.name
book.instances.append(i)
# editing / uploading new file
if user_form.file.data:
file = request.files['file']
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
id = book.id
filename = str(id) + "_" + secure_filename(file.filename)
fullpath = os.path.join(
app.config['UPLOAD_FOLDER'],
filename
)
name, file_extension = os.path.splitext(filename)
file.save(fullpath)
book.cover = ""
try:
get_cover(fullpath, name)
except Exception:
print("couldn't get cover")
book.file = filename
else:
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
db.session.commit()
flash("%s updated" % (title))
return redirect(url_for('show_book_by_id', id=id))
return render_template(
'edit_book_detail.html',
book=book_to_edit,
form=user_form,
light=app.config['LIGHT']
)
@app.route('/add-book', methods=['POST', 'GET'])
@check_light
def add_book():
upload_form = UploadForm()
allbooks = db.session.query(Book).all()
books_all = len(allbooks)
allauthors = db.session.query(Author).all()
authors_all = len(allauthors)
stacks_all = [s.stack_name for s in db.session.query(Stack.stack_name)]
categories = [
r.category for r in
db.session.query(Book.category).distinct()
]
allpotential = (
db.session.query(Book)
.filter(Book.file.contains('potential.pdf'))
.all()
)
books_potential = len(allpotential)
earliest = db.session.query(func.min(Book.year_published)).scalar()
latest = db.session.query(func.max(Book.year_published)).scalar()
if request.method == 'POST':
if upload_form.validate_on_submit():
title = upload_form.title.data
authors = upload_form.author.data
category = upload_form.category.data
message = upload_form.message.data
year_published = upload_form.year_published.data
sameness = upload_form.sameness.data
gender = upload_form.gender.data
diversity = upload_form.diversity.data
who = upload_form.who.data
if year_published == "":
year_published = None
# if upload with file
if upload_form.upload.data:
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
allbooks = db.session.query(Book).all()
id = len(allbooks)+1
filename = str(id) + "_" + secure_filename(file.filename)
fullpath = os.path.join(
app.config['UPLOAD_FOLDER'],
filename
)
name, file_extension = os.path.splitext(filename)
file.save(fullpath)
try:
cover = get_cover(fullpath, name)
except Exception:
cover = ''
extract_text(fullpath, name)
else:
flash('allowed file formats: %s' % ALLOWED_EXTENSIONS)
# if upload without file -> wishform, with potential PDF
if upload_form.wish.data:
# pdf generator
filename = 'potential.pdf'
file_extension = '.pdf'
cover = 'default_cover.gif'
ptitle = upload_form.title.data
pbook = Potential(ptitle)
db.session.add(pbook)
db.session.commit()
pbooks = Potential.query.all()
html_string = render_template(
'potential_pdf.html',
pbooks=pbooks
)
html = HTML(string=html_string)
html.write_pdf(target='app/uploads/potential.pdf')
book = Book(
title,
filename,
cover,
file_extension,
category,
year_published,
message,
sameness,
diversity,
gender,
who
)
db.session.add(book)
for author in authors:
author_name = author.get("author_name")
if author_name:
a = (
db.session.query(Author)
.filter_by(author_name=author_name)
.first()
)
if a is None:
a = Author(author_name=author_name)
db.session.add(a)
book.authors.append(a)
i = Instance(request.host, "add")
existing_ip = (
db.session
.query(Instance)
.filter_by(ip=request.host)
.first()
)
if existing_ip:
i.name = existing_ip.name
book.instances.append(i)
db.session.commit()
flash("%s added to the library" % (title))
return redirect(url_for('show_books'))
flash_errors(upload_form)
return render_template(
'add_book.html',
form=upload_form,
books_all=books_all,
authors_all=authors_all,
categories=categories,
stacks_all=stacks_all,
books_potential=books_potential,
earliest=earliest,
latest=latest,
light=app.config['LIGHT']
)
# Flash errors from the form if validation fails
def flash_errors(form):
for field, errors in form.errors.items():
for error in errors:
flash(u"Error in the %s field - %s" % (
getattr(form, field).label.text,
error
))
# Authors
@app.route('/authors/<int:id>')
def show_author_by_id(id):
author = Author.query.get(id)
if not author:
abort(404)
else:
return render_template(
'show_author_detail.html',
author=author,
light=app.config['LIGHT']
)
@app.route('/authors/<int:id>/edit', methods=['POST', 'GET'])
@check_light
def edit_author_by_id(id):
return "Ask the programmer."
# Stacks
@app.route('/stacks')
def show_stacks():
stacks = db.session.query(Stack).all()
return render_template(
'show_stacks.html',
stacks=stacks,
light=app.config['LIGHT']
)
@app.route('/stacks/add_stack', methods=['POST', 'GET'])
@check_light
def add_stack():
form = StackForm()
stacks = db.session.query(Stack).all()
if form.validate_on_submit():
stack_name = form.stack_name.data
stack_description = form.stack_description.data
stack_author = form.stack_author.data
stack = Stack(stack_name, stack_description, stack_author)
if form.stack_name.data:
stack = Stack(stack_name, stack_description, stack_author)
db.session.add(stack)
stacks = db.session.query(Stack).all()
return redirect(url_for('show_stacks'))
flash("%s stack created" % (stack_name))
return render_template(
'add_stack.html',
stacks=stacks,
form=form,
light=app.config['LIGHT']
)
@app.route('/stacks/tab/<int:id>', methods=['POST', 'GET'])
def show_stack_in_tab(id):
return show_stack_by_id(id, is_tab=True)
@app.route('/stacks/<int:id>', methods=['POST', 'GET'])
def show_stack_by_id(id, is_tab=False):
stack = Stack.query.get(id)
if not stack:
abort(404)
if not is_tab:
return render_template(
'show_stack_detail.html',
stack=stack,
light=app.config['LIGHT']
)
else:
return render_template(
'show_stack_detail_tab.html',
stack=stack,
light=app.config['LIGHT']
)
@app.route('/stacks/<int:id>/delete', methods=['POST', 'GET'])
@check_light
def remove_stack_by_id(id):
Stack.query.filter_by(id=id).delete()
db.session.commit()
return redirect(url_for('show_stacks'))
@app.route('/stacks/<int:id>/edit', methods=['POST', 'GET'])
@check_light
def edit_stack_by_id(id):
stack = Stack.query.filter_by(id=id).first()
form = EditStackForm(
edit_stack_name=stack.stack_name,
edit_stack_description=stack.stack_description
)
if request.method == 'POST':
if form.validate_on_submit():
stack_name = form.edit_stack_name.data
stack_description = form.edit_stack_description.data
stack.stack_name = stack_name
stack.stack_description = stack_description
db.session.commit()
return redirect(url_for('show_stack_by_id', id=id))
return render_template(
'edit_stack_detail.html',
stack=stack,
form=form,
light=app.config['LIGHT']
)
@app.route('/instances', methods=['POST', 'GET'])
@check_light
def show_instances():
all_instances = db.session.query(Instance).all()
instances = []
for instance in all_instances:
exists = False
for existing_inst in instances:
if existing_inst.name == instance.name:
exists = True
break
else:
exists = False
if not exists:
instances.append(instance)
if request.method == 'POST':
for item in request.form.items():
for i, itm in enumerate(item):
if i == 0:
oldname = itm
if i == 1:
name = itm
all_instances = (
db.session
.query(Instance)
.filter_by(name=oldname)
.all()
)
for instance in all_instances:
instance.name = name
db.session.commit()
return render_template(
'show_instances.html',
instances=instances,
light=app.config['LIGHT']
)
@app.route(
'/stacks/<int:stackid>/remove/<int:bookid>',
methods=['POST', 'GET']
)
@check_light
def remove_from_stack(bookid, stackid):
book = Book.query.get(bookid)
stack = Stack.query.get(stackid)
if book not in stack.books:
return render_template(
'show_book_detail.html',
book=book,
light=app.config['LIGHT']
)
stack.books.remove(book)
db.session.commit()
return render_template(
'show_book_detail.html',
book=book,
light=app.config['LIGHT']
)
# Search
view = ['1']
@app.route('/books', methods=['POST', 'GET'])
def show_books():
books = db.session.query(Book).order_by(Book.title)
search = SearchForm(request.form)
view.append('1')
viewby = '1'
if search.grid.data:
viewby = '2'
view.append('2')
return render_template(
'show_books_grid.html',
books=books,
form=search,
light=app.config['LIGHT']
)
if search.listview.data:
viewby = '1'
view.append('1')
return render_template(
'show_books.html',
books=books,
form=search,
light=app.config['LIGHT']
)
if request.method == 'POST':
newmsg = 'searched for: ' + search.search.data
socketio.emit('channel-' + str(1), {
'username': 'Search form',
'text': search.search.data,
'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M"))
}, broadcast=True)
my_new_chat = Chat(message=newmsg)
db.session.add(my_new_chat)
try:
db.session.commit()
except Exception:
db.session.rollback()
return redirect((url_for(
'search_results',
searchtype=search.select.data,
query=search.search.data,
viewby=viewby
)))
return render_template(
'show_books.html',
books=books,
form=search,
light=app.config['LIGHT']
)
@app.route('/search/<searchtype>/<viewby>/<query>', methods=['POST', 'GET'])
def search_results(searchtype, query, viewby):
search = SearchForm(request.form, search=query)
results = (
Book.query
.filter(Book.title.contains(query))
.order_by(Book.title)
)
allbooks = set(Book.query.all())
viewby = view[-1]
if searchtype == 'Title':
results = (
Book.query
.filter(Book.title.contains(query))
.order_by(Book.title)
)
if searchtype == 'Category':
results = (
Book.query
.filter(Book.category.contains(query))
.order_by(Book.title)
)
if searchtype == 'Author':
results = (
db.session.query(Book)
.join(Book.authors)
.filter(Author.author_name.contains(query))
.order_by(Book.title)
)
if searchtype == 'Stack':
results = (
db.session.query(Book)
.join(Book.stacks)
.filter(Stack.stack_name.contains(query))
.order_by(Book.title)
)
if searchtype == 'Outliers':
results = Book.query.filter(Book.sameness > 50).order_by(Book.title)
if searchtype == 'All':
results = (
Book.query.filter(Book.title.contains(query))
.union(Book.query.filter(Book.category.contains(query)))
.union(Book.query.filter(Book.year_published.contains(query)))
.union(
db.session.query(Book)
.join(Book.authors)
.filter(Author.author_name.contains(query))
)
.union(
db.session.query(Book)
.join(Book.stacks)
.filter(Stack.stack_name.contains(query))
).order_by(Book.title)
)
if results.count() == 0:
books = Book.query.filter(Book.file.like('potential.pdf'))
upload_form = UploadForm(title=query, author='')
return render_template(
'red_link.html',
form=upload_form,
title=query,
books=books,
light=app.config['LIGHT']
)
count = results.count()
whole = Book.query.count()
percentage = float(count / whole * 100)
fbooks = set(results)
books_all = allbooks - fbooks
if search.listview.data:
view.append('1')
return render_template(
'results.html',
books=results,
form=search,
query=query,
books_all=books_all,
searchtype=search.select.data,
count=count,
whole=whole,
percentage=percentage,
light=app.config['LIGHT']
)
if search.grid.data:
view.append('2')
return render_template(
'results_grid.html',
books=results,
form=search,
query=query,
books_all=books_all,
searchtype=search.select.data,
count=count,
whole=whole,
percentage=percentage,
light=app.config['LIGHT']
)
if request.method == 'POST':
newmsg = 'searched for: ' + search.search.data
socketio.emit('channel-' + str(1), {
'username': 'Search form',
'text': search.search.data,
'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M"))
}, broadcast=True)
my_new_chat = Chat(message=newmsg)
db.session.add(my_new_chat)
try:
db.session.commit()
except Exception:
db.session.rollback()
query = search.search.data
results = []
if viewby == '1':
return redirect((url_for(
'search_results',
searchtype=search.select.data,
query=search.search.data,
viewby=viewby
)))
else:
return redirect((url_for(
'search_results',
searchtype=search.select.data,
query=search.search.data,
viewby=viewby
)))
if viewby == '2':
return render_template(
'results_grid.html',
form=search,
books=results,
books_all=books_all,
searchtype=search.select.data,
query=query,
count=count,
whole=whole,
percentage=percentage,
light=app.config['LIGHT']
)
else:
return render_template(
'results.html',
form=search,
books=results,
books_all=books_all,
searchtype=search.select.data,
query=query,
count=count,
whole=whole,
percentage=percentage,
light=app.config['LIGHT']
)
autocomplete_suggestions = []
autocomplete.load()
@app.route('/autocomplete_suggestions', methods=['GET', 'POST'])
def autocomplete_search():
if request.method == 'GET':
query = request.args.get('q')
query_tokenized = query.split()
word_1 = query_tokenized[-2]
word_2 = query_tokenized[-1]
autocomplete_output = autocomplete.predict(word_1, word_2)
autocomplete_suggestions.clear()
for suggestion, score in autocomplete_output:
autocomplete_suggestions.append(suggestion)
return Response(
json.dumps(autocomplete_suggestions),
mimetype='application/json'
)
@app.route('/search_annot', methods=['POST', 'GET'])
def search_annot():
books = db.session.query(Book).all()
name = str(request.args.get('query'))
annot = get_annotations()
res = get_annot_results(annot, name)
return render_template(
'results_annot.html',
name=name,
annot=annot,
res=res,
books=books
)
# STACKS!
@app.route('/add_to_stack/<int:id>', methods=['GET', 'POST'])
@check_light
def add_to_stack(id):
stacks = db.session.query(Stack).all()
add_form = AddtoStackForm(request.form)
add_form.select_stack.choices = [
(stack.id, stack.stack_name)
for stack in stacks
]
if request.method == 'GET':
book = Book.query.get(id)
return render_template(
'add_to_stacks.html',
id=id,
stacks=stacks,
book=book,
add_form=add_form,
light=app.config['LIGHT']
)
else:
stack = Stack.query.get(int(add_form.select_stack.data))
book = Book.query.get(id)
stack.books.append(book)
db.session.commit()
return render_template(
'show_stack_detail.html',
stack=stack,
light=app.config['LIGHT']
)
@app.route('/export/csv', methods=['GET'])
@check_light
def export_csv():
output = io.StringIO()
fields = Book.__mapper__.columns
fieldnames = []
for columns in fields:
fieldnames.append(columns.name)
i = inspect(Book)
referred_classes = [r.mapper.class_ for r in i.relationships]
referred_classes_tablenames = [
r.mapper.class_.__tablename__
for r in i.relationships
]
csv = DictWriter(
output,
fieldnames + referred_classes_tablenames
)
csv.writeheader()
for book in Book.query.order_by("title"):
row = {}
for col in fieldnames:
row[col] = getattr(book, col)
for col in referred_classes:
subattr = []
for subcol in getattr(book, col.__tablename__):
for metacol in subcol.__mapper__.columns:
query = metacol.name
if query != "id":
this = getattr(subcol, query)
subattr.append(this)
row[col.__tablename__] = " | ".join(subattr)
csv.writerow(row)
resp = Response(output.getvalue(), mimetype="text/csv")
resp.headers["Content-Disposition"] = "attachment;filename=export.csv"
return resp
@app.route('/import/csv', methods=['POST', 'GET'])
@check_light
def import_csv():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
else:
file = request.files['file']
for row in DictReader(codecs.iterdecode(file, 'utf-8')):
numberadded = 0
book = (
db.session.query(Book)
.filter(Book.title == row['title'])
.first()
)
if book:
print("allreadyexists")
else:
cover = ''
if row['file'] == '':
file = 'potential.pdf'
file_extension = '.pdf'
cover = "default_cover.gif"
ptitle = row['title']
pbook = Potential(ptitle)
db.session.add(pbook)
db.session.commit()
pbooks = Potential.query.all()
html_string = render_template(
'potential_pdf.html',
pbooks=pbooks
)
html = HTML(string=html_string)
html.write_pdf(target='app/uploads/potential.pdf')
else:
fullpath = os.path.join(
app.config['UPLOAD_FOLDER'], row['file']
)
name, file_extension = os.path.splitext(row['file'])
try:
cover = get_cover(fullpath, name)
except Exception:
print("couldn't get cover")
file = row['file']
if row['year_published']:
year_published = int(row['year_published'])
else:
year_published = None
book = Book(
row['title'],
file,
cover,
row['fileformat'],
row['category'],
year_published,
None, None, None, None, None
)
if row['scapeX']:
book.scapeX = float(row['scapeX'])
if row['scapeY']:
book.scapeY = float(row['scapeY'])
db.session.add(book)
numberadded = numberadded+1
authors = row['authors'].split('|')
authors = [x.strip() for x in authors]
for author in authors:
if author:
a = (
db.session.query(Author)
.filter_by(author_name=author)
.first()
)
if a is None:
a = Author(author_name=author)
db.session.add(a)
book.authors.append(a)
db.session.commit()
return render_template(
'import_csv.html',
numberadded=numberadded,
light=app.config['LIGHT']
)
@app.route('/emptycataloguexpubxpubfuck', methods=['POST', 'GET'])
@check_light
def empty_catalogue():
meta = db.metadata
for table in reversed(meta.sorted_tables):
if (str(table) == "books"
or str(table) == "authors"
or str(table) == "books_authors"):
db.session.execute(table.delete())
db.create_all()
db.session.commit()
return "ALL CLEARED"
###
# The API
###
@app.route('/api/books', methods=['GET'])
def get_books():
books = Book.query.all()
data = books_schema.dump(books)
return jsonify({'books': data})
@app.route('/api/books/<int:id>', methods=['GET'])
def get_book_by_id(id):
book = Book.query.get(id)
data = book_schema.dump(book)
if not data:
return jsonify({"message": "Book could not be found."}), 400
else:
return jsonify({'book': data})
@app.route('/api/chats', methods=['GET'])
def get_chat():
chats = Chat.query.all()
data = chats_schema.dump(chats)
return jsonify({'chat': data})
###
# The functions below should be applicable to all Flask apps.
###
@app.after_request
def add_header(response):
"""
Add headers to both force latest IE rendering engine or Chrome Frame,
and also to cache the rendered page for 10 minutes.
"""
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
response.headers['Cache-Control'] = 'no-cache'
return response
@app.errorhandler(404)
def page_not_found(error):
"""Custom 404 page."""
return render_template('404.html', light=app.config['LIGHT']), 404
# SOCKET for the chat
@socketio.on('new_message')
def new_message(message):
emit('channel-' + str(message['channel']), {
'username': message['username'],
'text': message['text'],
'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M"))
}, broadcast=True)
my_new_chat = Chat(message=message['text'])
db.session.add(my_new_chat)
try:
db.session.commit()
except Exception:
db.session.rollback()
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port='8080')