make pretty filenames for downloads; remove random books section on most pages

pull/5/head
Jan Broer 8 years ago
parent 2b846b1e6b
commit f163ef2202

@ -155,6 +155,7 @@ class Books(Base):
id = Column(Integer,primary_key=True) id = Column(Integer,primary_key=True)
title = Column(String) title = Column(String)
sort = Column(String) sort = Column(String)
author_sort = Column(String)
timestamp = Column(String) timestamp = Column(String)
pubdate = Column(String) pubdate = Column(String)
series_index = Column(String) series_index = Column(String)
@ -170,9 +171,10 @@ class Books(Base):
ratings = relationship('Ratings', secondary=books_ratings_link, backref='books') ratings = relationship('Ratings', secondary=books_ratings_link, backref='books')
languages = relationship('Languages', secondary=books_languages_link, backref='books') languages = relationship('Languages', secondary=books_languages_link, backref='books')
def __init__(self, title, sort, timestamp, pubdate, series_index, last_modified, path, has_cover, authors, tags): def __init__(self, title, sort, author_sort, timestamp, pubdate, series_index, last_modified, path, has_cover, authors, tags):
self.title = title self.title = title
self.sort = sort self.sort = sort
self.author_sort = author_sort
self.timestamp = timestamp self.timestamp = timestamp
self.pubdate = pubdate self.pubdate = pubdate
self.series_index = series_index self.series_index = series_index
@ -181,11 +183,8 @@ class Books(Base):
self.has_cover = has_cover self.has_cover = has_cover
self.tags = tags self.tags = tags
def __repr__(self): def __repr__(self):
return u"<Books('{0},{1}{2}{3}{4}{5}{6}{7}')>".format(self.title, self.sort, self.timestamp, self.pubdate, self.series_index, self.last_modified ,self.path, self.has_cover) return u"<Books('{0},{1}{2}{3}{4}{5}{6}{7}{8}')>".format(self.title, self.sort, self.author_sort, self.timestamp, self.pubdate, self.series_index, self.last_modified ,self.path, self.has_cover)
Base.metadata.create_all(engine) Base.metadata.create_all(engine)
Session = sessionmaker() Session = sessionmaker()

@ -8,6 +8,8 @@ import smtplib
import sys import sys
import os import os
import traceback import traceback
import re
import unicodedata
from StringIO import StringIO from StringIO import StringIO
from email import encoders from email import encoders
from email.MIMEBase import MIMEBase from email.MIMEBase import MIMEBase
@ -125,3 +127,25 @@ def get_attachment(file_path):
message = ('The requested file could not be read. Maybe wrong ' message = ('The requested file could not be read. Maybe wrong '
'permissions?') 'permissions?')
return None return None
def get_valid_filename(value):
"""
Returns the given string converted to a string that can be used for a clean
filename. Limits num characters to 128 max.
"""
value = value[:128]
re_slugify = re.compile('[^\w\s-]', re.UNICODE)
value = unicodedata.normalize('NFKD', value)
re_slugify = re.compile('[^\w\s-]', re.UNICODE)
value = unicode(re_slugify.sub('', value).strip())
value = re.sub('[\s]+', '_', value, flags=re.U)
return value
def get_normalized_author(value):
"""
Normalizes sorted author name
"""
value = unicodedata.normalize('NFKD', value)
value = re.sub('[^\w,\s]', '', value, flags=re.U)
value = " ".join(value.split(", ")[::-1])
return value

@ -1,5 +1,6 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block body %} {% block body %}
{% if random.count() > 0 %}
<div class="discover"> <div class="discover">
<h2>Discover (Random Books)</h2> <h2>Discover (Random Books)</h2>
<div class="row"> <div class="row">
@ -34,6 +35,7 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
{% endif %}
<div class="discover load-more"> <div class="discover load-more">
<h2>{{title}}</h2> <h2>{{title}}</h2>
<div class="row"> <div class="row">

@ -7,6 +7,7 @@ from flask import Flask, render_template, session, request, Response, redirect,
from cps import db, config, ub, helper from cps import db, config, ub, helper
import os import os
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from sqlalchemy.sql.expression import false
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from math import ceil from math import ceil
from flask.ext.login import LoginManager, login_user, logout_user, login_required, current_user from flask.ext.login import LoginManager, login_user, logout_user, login_required, current_user
@ -15,6 +16,7 @@ import requests, zipfile
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
from functools import wraps from functools import wraps
import base64 import base64
from sqlalchemy.sql import *
app = (Flask(__name__)) app = (Flask(__name__))
@ -179,7 +181,7 @@ def feed_discover():
entries = db.session.query(db.Books).order_by(func.random()).limit(config.NEWEST_BOOKS) entries = db.session.query(db.Books).order_by(func.random()).limit(config.NEWEST_BOOKS)
off = 0 off = 0
xml = render_template('feed.xml', entries=entries, next_url="/feed/discover?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off))) xml = render_template('feed.xml', entries=entries, next_url="/feed/discover?start_index=%d" % (int(config.NEWEST_BOOKS) + int(off)))
response= make_response(xml) response = make_response(xml)
response.headers["Content-Type"] = "application/xml" response.headers["Content-Type"] = "application/xml"
return response return response
@ -204,8 +206,13 @@ def get_opds_download_link(book_id, format):
book = db.session.query(db.Books).filter(db.Books.id == book_id).first() book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first() data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first()
helper.update_download(book_id, int(current_user.id)) helper.update_download(book_id, int(current_user.id))
author = helper.get_normalized_author(book.author_sort)
file_name = book.title
if len(author) > 0:
file_name = author+'-'+file_name
file_name = helper.get_valid_filename(file_name)
response = make_response(send_from_directory(os.path.join(config.DB_ROOT, book.path), data.name + "." +format)) response = make_response(send_from_directory(os.path.join(config.DB_ROOT, book.path), data.name + "." +format))
response.headers["Content-Disposition"] = "attachment; filename=%s.%s" % (data.name, format) response.headers["Content-Disposition"] = "attachment; filename=%s.%s" % (file_name, format)
return response return response
@app.route("/", defaults={'page': 1}) @app.route("/", defaults={'page': 1})
@ -223,7 +230,7 @@ def index(page):
@app.route("/hot", defaults={'page': 1}) @app.route("/hot", defaults={'page': 1})
@app.route('/hot/page/<int:page>') @app.route('/hot/page/<int:page>')
def hot_books(page): def hot_books(page):
random = db.session.query(db.Books).order_by(func.random()).limit(config.RANDOM_BOOKS) random = db.session.query(db.Books).filter(false())
# if page == 1: # if page == 1:
# entries = db.session.query(db.Books).filter(db.Books.ratings.any(db.Ratings.rating > 9)).order_by(db.Books.last_modified.desc()).limit(config.NEWEST_BOOKS) # entries = db.session.query(db.Books).filter(db.Books.ratings.any(db.Ratings.rating > 9)).order_by(db.Books.last_modified.desc()).limit(config.NEWEST_BOOKS)
# else: # else:
@ -236,9 +243,13 @@ def hot_books(page):
entries = list() entries = list()
for book in hot_books: for book in hot_books:
entries.append(db.session.query(db.Books).filter(db.Books.id == book.Downloads.book_id).first()) entries.append(db.session.query(db.Books).filter(db.Books.id == book.Downloads.book_id).first())
numBooks = len(all_books.all())
pagination = Pagination(page, config.NEWEST_BOOKS, len(all_books.all())) pages = int(ceil(numBooks / float(config.NEWEST_BOOKS)))
return render_template('index.html', random=random, entries=entries, pagination=pagination, title="Hot Books (most downloaded)") if pages > 1:
pagination = Pagination(page, config.NEWEST_BOOKS, len(all_books.all()))
return render_template('index.html', random=random, entries=entries, pagination=pagination, title="Hot Books (most downloaded)")
else:
return render_template('index.html', random=random, entries=entries, title="Hot Books (most downloaded)")
@app.route("/stats") @app.route("/stats")
def stats(): def stats():
@ -272,7 +283,7 @@ def category_list():
@app.route("/category/<name>") @app.route("/category/<name>")
def category(name): def category(name):
random = db.session.query(db.Books).order_by(func.random()).limit(config.RANDOM_BOOKS) random = db.session.query(db.Books).filter(false())
if name != "all": if name != "all":
entries = db.session.query(db.Books).filter(db.Books.tags.any(db.Tags.name.like("%" +name + "%" ))).order_by(db.Books.last_modified.desc()).all() entries = db.session.query(db.Books).filter(db.Books.tags.any(db.Tags.name.like("%" +name + "%" ))).order_by(db.Books.last_modified.desc()).all()
else: else:
@ -281,7 +292,7 @@ def category(name):
@app.route("/series/<name>") @app.route("/series/<name>")
def series(name): def series(name):
random = db.session.query(db.Books).order_by(func.random()).limit(config.RANDOM_BOOKS) random = db.session.query(db.Books).filter(false())
entries = db.session.query(db.Books).filter(db.Books.series.any(db.Series.name.like("%" +name + "%" ))).order_by(db.Books.series_index).all() entries = db.session.query(db.Books).filter(db.Books.series.any(db.Series.name.like("%" +name + "%" ))).order_by(db.Books.series_index).all()
return render_template('index.html', random=random, entries=entries, title="Series: %s" % name) return render_template('index.html', random=random, entries=entries, title="Series: %s" % name)
@ -309,7 +320,7 @@ def author_list():
@app.route("/author/<name>") @app.route("/author/<name>")
def author(name): def author(name):
random = db.session.query(db.Books).order_by(func.random()).limit(config.RANDOM_BOOKS) random = db.session.query(db.Books).filter(false())
entries = db.session.query(db.Books).filter(db.Books.authors.any(db.Authors.name.like("%" + name + "%"))).all() entries = db.session.query(db.Books).filter(db.Books.authors.any(db.Authors.name.like("%" + name + "%"))).all()
return render_template('index.html', random=random, entries=entries, title="Author: %s" % name) return render_template('index.html', random=random, entries=entries, title="Author: %s" % name)
@ -346,8 +357,13 @@ def get_download_link(book_id, format):
book = db.session.query(db.Books).filter(db.Books.id == book_id).first() book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first() data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first()
helper.update_download(book_id, int(current_user.id)) helper.update_download(book_id, int(current_user.id))
author = helper.get_normalized_author(book.author_sort)
file_name = book.title
if len(author) > 0:
file_name = author+'-'+file_name
file_name = helper.get_valid_filename(file_name)
response = make_response(send_from_directory(os.path.join(config.DB_ROOT, book.path), data.name + "." +format)) response = make_response(send_from_directory(os.path.join(config.DB_ROOT, book.path), data.name + "." +format))
response.headers["Content-Disposition"] = "attachment; filename=%s.%s" % (data.name, format) response.headers["Content-Disposition"] = "attachment; filename=%s.%s" % (file_name, format)
return response return response
@app.route('/register', methods = ['GET', 'POST']) @app.route('/register', methods = ['GET', 'POST'])

Loading…
Cancel
Save