From b72268810036f8f195df7b44f4cb95b4f4762ef6 Mon Sep 17 00:00:00 2001 From: Jordan Date: Thu, 3 Aug 2023 01:06:37 -0700 Subject: roka: misc housekeeping --- lib/books.py | 34 ++++++++++------------------------ roka.py | 43 +++++++++++++++++++------------------------ 2 files changed, 29 insertions(+), 48 deletions(-) diff --git a/lib/books.py b/lib/books.py index 95df374..3244d13 100644 --- a/lib/books.py +++ b/lib/books.py @@ -9,16 +9,11 @@ from datetime import timedelta from flask import Flask from lib.tinytag import TinyTag -ABS_PATH = os.path.dirname(os.path.abspath(__file__)) -CACHE_PATH = os.path.join(ABS_PATH, '../', 'cache') -JSON_PATH = os.path.join(CACHE_PATH, 'audiobooks.json') - class Books: - def __init__(self): - ''' - Book-related handlers (r/w cache) and track discovery - ''' - if os.path.exists(JSON_PATH): + def __init__(self, cache_path): + self.cache_path = cache_path + self.json_path = os.path.join(cache_path, 'audiobooks.json') + if os.path.exists(self.json_path): self._cache = self._read_cache() else: self._cache = {} @@ -52,24 +47,21 @@ class Books: ''' Dump contents of :books: to :json_path: ''' - if not os.path.exists(CACHE_PATH): - os.mkdir(CACHE_PATH) - with open(JSON_PATH, 'w') as cache: + if not os.path.exists(self.cache_path): + os.mkdir(self.cache_path) + with open(self.json_path, 'w') as cache: json.dump(self.books, cache, indent=4) def _read_cache(self): ''' Return dict of existing cache ''' - with open(JSON_PATH, 'r') as cache: + with open(self.json_path, 'r') as cache: data = json.load(cache) return data def _validate(self, v, b): - ''' - Returns :v: if :v: and v.isspace(), otherwise :b: - ''' if v and not v.isspace(): return v @@ -84,10 +76,7 @@ class Books: def scan_books(self, audiobook_path=None): ''' - Discover audiobooks under :root_path: and populate books object - - :cache: existing JSON cache, used to determine which content is new - (existing content is not re-hashed) + Discover audiobooks under :root_path: and populate books ''' ex = self._get_path_hash_dict() dirs = self._get_dirs(audiobook_path) @@ -106,8 +95,7 @@ class Books: def _check_dir(self, path): ''' - Determine if :path: contains (supported) audio files; return populated - book dict or None + Determine if :path: contains (supported) audio files ''' ext = ['mp3'] # m4b seems to be unsupported by Apple is_book = False @@ -203,5 +191,3 @@ class Books: book['duration_str'] = duration_str.split('.')[0] return (folder_hash, book) - - return None diff --git a/roka.py b/roka.py index c9643b2..effdbe2 100755 --- a/roka.py +++ b/roka.py @@ -9,26 +9,19 @@ from flask.globals import app_ctx from lib.books import Books from lib.util import check_auth, escape, generate_rss, read_cache -abs_path = os.path.dirname(os.path.abspath(__file__)) app = Flask(__name__) -config_path = os.path.join(abs_path, 'app.cfg') -config_exists = os.path.exists(config_path) -if config_exists or __name__.startswith('uwsgi'): - app.config.from_pyfile(config_path) -cache_path = os.path.join(abs_path, 'cache') -json_path = os.path.join(cache_path, 'audiobooks.json') +CONFIG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'app.cfg') +if os.path.exists(CONFIG_PATH) or __name__.startswith('uwsgi'): + app.config.from_pyfile(CONFIG_PATH) +CACHE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'cache') +JSON_PATH = os.path.join(CACHE_PATH, 'audiobooks.json') @app.route('/') def list_books(): ''' Book listing and audiobook RSS/file download - - :a: audiobook hash; if provided without :f: (track) return RSS - :f: file hash; requires associated audiobook (:a:) to download - - Listing of audiobooks returned if no params provided ''' - books = read_cache(json_path) + books = read_cache(JSON_PATH) book = request.args.get('a') # audiobook hash track = request.args.get('f') # file hash @@ -42,29 +35,32 @@ def list_books(): return send_file(track_path, conditional=True) # serve up audiobook RSS feed; only audiobook hash provided - elif book: + if book: if not books.get(book): return 'book not found', 404 rss = generate_rss(request.base_url, book, books) return Response(rss, mimetype='text/xml') - else: - auth = request.authorization - if not auth or not check_auth(app, auth.username, auth.password): - form = {'WWW-Authenticate': 'Basic realm="o/"'} - return Response('unauthorized', 401, form) + # return index if authenticated + auth = request.authorization + if not auth or not check_auth(app, auth.username, auth.password): + form = {'WWW-Authenticate': 'Basic realm="o/"'} + return Response('unauthorized', 401, form) - return render_template('index.html', books=books, + return render_template('index.html', books=books, show_path=app.config.get('SHOW_PATH', True)) def generate(static_path, base_url, audiobook_dirs): + ''' + Static generation of index pages and RSS feeds + ''' static_index_path = os.path.join(static_path, 'index.html') books = Books() books.scan_books(audiobook_dirs) books.write_cache() - books = read_cache(json_path) + books = read_cache(JSON_PATH) # A bit of a hack, but push to the app context stack so we can render a # template outside of a Flask request with app.app_context(): @@ -115,13 +111,12 @@ if __name__ == '__main__': config = objectview(json.loads(args.config)) # override app.cfg app.config.from_object(config) - elif not config_exists: + elif not os.path.exists(CONFIG_PATH): raise Exception(f"Config file '{config_path}' doesn't exist") root_path = os.path.expanduser(app.config['ROOT_PATH']) - if args.scan: - books = Books() + books = Books(CACHE_PATH) books.scan_books(root_path) books.write_cache() elif args.static_path: -- cgit v1.2.3-54-g00ecf