|
#!/usr/bin/env python3 |
|
|
|
# randpage.py: display a random page from a directory of pdf files. |
|
# Copyright 2019 Jason Pepas |
|
# Released under the terms of the MIT license, see https://opensource.org/license/mit |
|
|
|
# Usage: |
|
# Open a random page using Preview.app: |
|
# $ ./randpage.py |
|
# Run as a webapp on localhost:8000: |
|
# $ ./randpage.py --serve |
|
|
|
import sys |
|
import os |
|
import random |
|
import subprocess |
|
|
|
|
|
def check_deps(): |
|
"check if we have all of the dependencies installed" |
|
if os.system("which -s pdfinfo") != 0: |
|
sys.stderr.write("Error: pdfinfo not installed.\n") |
|
sys.stderr.write("Try 'brew install xpdf'.\n") |
|
sys.exit(1) |
|
if os.system("which -s pdftk") != 0: |
|
sys.stderr.write("Error: pdftk not installed.\n") |
|
sys.stderr.write("Try 'brew install pdftk-java'.\n") |
|
sys.exit(1) |
|
if os.system("which -s exiftool") != 0: |
|
sys.stderr.write("Error: exiftool not installed.\n") |
|
sys.stderr.write("Try 'brew install exiftool'.\n") |
|
sys.exit(1) |
|
|
|
|
|
def random_book(path): |
|
"return a random book among the books in the current directory." |
|
books = [fname for fname in os.listdir(path) if fname.endswith('.pdf')] |
|
return random.choice(books) |
|
|
|
|
|
def page_count(fname): |
|
"return the page count of the given book." |
|
cmd = "set -e -o pipefail; pdfinfo \"%s\" | grep Pages: | awk '{print $2}'" % fname |
|
output = subprocess.check_output(cmd, shell=True) |
|
return int(output) |
|
|
|
|
|
def pluck_page(book_fname, pagenum): |
|
"extract the given page from the given book." |
|
cmd = "set -e; pdftk \"%s\" cat %s output /tmp/random-page.pdf" % (book_fname, pagenum) |
|
subprocess.check_call(cmd, shell=True) |
|
# set the metadata title of the pdf to indicate the book title and page number. |
|
title = "%s, page %s" % (book_fname.split('/')[-1], pagenum) |
|
cmd = "set -e; exiftool -Title=\"%s\" /tmp/random-page.pdf" % title |
|
subprocess.check_call(cmd, shell=True) |
|
return "/tmp/random-page.pdf" |
|
|
|
|
|
def display_page(fname): |
|
"display the extracted book page." |
|
subprocess.check_call("set -e; open %s" % fname, shell=True) |
|
|
|
|
|
def display_random_page(books_path): |
|
"display a random page from a random book." |
|
book_fname = random_book(books_path) |
|
pages = page_count(book_fname) |
|
pagenum = random.randrange(pages) + 1 |
|
print("%s, page %s of %s" % (book_fname, pagenum, pages)) |
|
page_fname = pluck_page(book_fname, pagenum) |
|
display_page(page_fname) |
|
|
|
|
|
def serve(books_path): |
|
"run as a webapp on port 8000." |
|
import flask |
|
application = flask.Flask(__name__) |
|
|
|
@application.route("/") |
|
def GET_root(methods=['GET']): |
|
book_fname = random_book(books_path) |
|
pages = page_count(books_path + book_fname) |
|
pagenum = random.randrange(pages) + 1 |
|
page_fname = pluck_page(books_path + book_fname, pagenum) |
|
with open(page_fname, 'rb') as f: |
|
pdf = f.read() |
|
response = flask.make_response(pdf) |
|
response.headers['Content-Type'] = 'application/pdf' |
|
response.headers['Content-Disposition'] = \ |
|
'inline; filename=%s' % book_fname |
|
response.headers["x-filename"] = book_fname |
|
response.headers["Access-Control-Expose-Headers"] = 'x-filename' |
|
return response |
|
|
|
application.run('0.0.0.0', port=8000, debug=False) |
|
|
|
|
|
if __name__ == "__main__": |
|
check_deps() |
|
books_path = './' |
|
if '--serve' in sys.argv: |
|
serve(books_path) |
|
else: |
|
display_random_page(books_path) |