diff --git a/app.py b/app.py index 22ec1fe..df3809e 100644 --- a/app.py +++ b/app.py @@ -5,6 +5,34 @@ from datetime import date # used for daily verse import subprocess # use of "bible" system application for parsing and returning Bible in KJV0 import shlex # input security import sqlite3 +import string +DEBUG = 2 +DEBUG_OUT = 0 + +""" +NOTES +- working on getting multi-search terms working right +Lookup_bookname does not like it lol. + +To-do: +- Add data and function for Webster 1828 dictionary lookup +--https://github.com/DataWar/1828-dictionary +--https://github.com/mnjrupp/Android_SQLite_Dictionary_1828 +--https://github.com/gapmiss/kingdom-study-tools-for-obsidian/tree/main/dictionary/ +- Add data and function for Thesaurus to implement fuzzy search +--https://github.com/zaibacu/thesaurus +""" + +def dbg(message): + # if DEBUG is at or above a value of one, a call from debug level one will print red + if DEBUG >= 1: + print(f'\033[91m{message}\033[0m') +def dbg2(message): + # if DEBUG is at or above a value of two, a call from debug level one will print green + if DEBUG >= 2: + print(f'\033[32m{message}\033[0m') +dbg("Debug Level 1 Enabled") +dbg2("Debug Level 2 Enabled") kjv_db = sqlite3.connect("kjv.db") kjv_cur = kjv_db.cursor() @@ -18,20 +46,35 @@ idx_chapter = 2 idx_verse = 3 idx_text = 4 -def lookup_one_verse(id): - return(kjv_cur.execute("SELECT * FROM t_kjv WHERE id = {};".format(id)).fetchone()) +def lookup_one_verse(verse_id): + dbg("lookup_one_verse({})".format(verse_id)) + return(kjv_cur.execute("SELECT * FROM t_kjv WHERE id = {};".format(verse_id)).fetchone()) -def lookup_bookname(id): - return kjv_cur.execute("SELECT n FROM key_english WHERE b = {}".format(id)).fetchone()[0] +def lookup_bookname(book_id): + dbg2("lookup_bookname({})".format(book_id)) + result = kjv_cur.execute("SELECT n FROM key_english WHERE b = {}".format(book_id)).fetchone()[0] + dbg("lookup_bookname: {}".format(result)) + return result -def response_json(scripture): + +def lookup_contains(kw): + results = kjv_cur.execute("SELECT * FROM t_kjv WHERE t LIKE '%{}%';".format(kw)).fetchall() + dbg("lookup_contains({}) {} results".format(kw,len(results))) + return results + +def lookup_contains_exact(kw): + results = kjv_cur.execute("SELECT * FROM t_kjv WHERE t LIKE '%{}%';".format(kw)).fetchall() + dbg("lookup_contains({}) {} results".format(kw,len(results))) + return results + +def response_dict(scripture): verse = { "bookname": lookup_bookname(scripture[idx_book]), "chapter": scripture[idx_chapter], "verse": scripture[idx_verse], "text": scripture[idx_text], } - return (jsonify(verse)) + return (verse) def response_text(scripture): bookname = lookup_bookname(scripture[idx_book]) @@ -54,14 +97,45 @@ def response_rich(scripture): return (response_html.read().format(passage = passage, text = text) + css.read()) -def response(scripture): +def response_single(scripture): + dbg2("response_single({})".format(scripture)) arg_view = request.args.get("view", None) + dbg("->requested_format = {}".format(arg_view)) if arg_view == "plain": return(response_text(scripture)) elif arg_view == "rich": return(response_rich(scripture)) else: - return(response_json(scripture)) + response = response_dict(scripture) + return jsonify(response) + +def response_multi(scriptures): + dbg2("response_multi({})".format(scriptures)) + response = [] + arg_view = request.args.get("view", None) + dbg("search ->requested_format = {}".format(arg_view)) + + if arg_view == "plain": + for scripture in scriptures: + dbg2("for scripture in scriptures content: {}".format(scripture)) + response.append(response_text(scripture)) + elif arg_view == "rich": + for scripture in scriptures: + dbg2("for scripture in scriptures content: {}".format(scripture)) + response.append(response_rich(scripture)) + else: + for scripture in scriptures: + dbg2("for scripture in scriptures content: {}".format(scripture)) + response.append(response_dict(scripture)) + + return(response) + + +def thesarus(word): + return word +def dictionary(word): + return word + @app.errorhandler(404) def page_not_found(e): @@ -78,7 +152,7 @@ def idx(): def random_verse(): rand_id = random.SystemRandom().choice(verse_ids) scripture = lookup_one_verse(rand_id) - return(response(scripture)) + return(response_single(scripture)) #backwards-compatibility @app.get('/t/votd', defaults={'view':'plain'}) @@ -88,8 +162,63 @@ def verse_of_the_day(): #this is deterministic because of today's date being used as the seed random.seed(today) scripture = lookup_one_verse(random.choice(verse_ids)) - return(response(scripture)) + return(response_single(scripture)) +# splits by delimiter then checks for any special characters +# if special characters are found, the query is rejected +def clean_keywords(kwds): + kwds = kwds.split(',') + for kwd in kwds: + if not kwd.isalpha(): + return False + dbg("clean_keywords = ({})".format(kwds)) + return kwds + + +def search_and(cleaned_keywords): + results = [] + for keyword in cleaned_keywords: + dbg("search->for keyword in database({})".format(keyword)) + #This is groups of results per word. Must check between groups. + results.append(lookup_contains(keyword)) + return (results) + +def search_any(cleaned_keywords): + results = [] + for keyword in cleaned_keywords: + dbg("search->for keyword in database({})".format(keyword)) + for result in lookup_contains(keyword): + results.append(result) + dbg("==> search_any: {} results".format(len(results))) + return(results) + + +@app.get("/search") +def search(): + keywords = request.args.get("kw", None) + dbg("search({})".format(keywords)) + if keywords: + cleaned_keywords = clean_keywords(keywords) + if not clean_keywords: + return ("Invalid Query: Special Characters") + else: + return ("No Query") + + if request.args.get("operator",None) == "and": + results = search_and(cleaned_keywords) + else: + results = search_any(cleaned_keywords) + + response_list = response_multi(results) + + arg_view = request.args.get("view", None) + if arg_view == "plain" or arg_view == "rich": + response = "
".join(response_list) + else: + response = jsonify(response_list) + + dbg2("Search Response: {}".format(response)) + return response @app.get("/qwerty") diff --git a/human_readable.css b/human_readable.css index 208cc7e..b88eaf9 100644 --- a/human_readable.css +++ b/human_readable.css @@ -2,9 +2,6 @@ html{ font-family: sans-serif; font-size: 50pt; - height: 100%; width: 768px; - overflow: hidden; - display: table; } diff --git a/index.html b/index.html index f7befe0..3eae9d6 100644 --- a/index.html +++ b/index.html @@ -68,6 +68,12 @@ default: json search default: faith show default: john3:16 +?op= +- Multi-keyword search operator +- and - both keywords must be in verse +- any - any keyword must be in a verse +search default: any + ?fz= - on - fuzzy search on default: off @@ -78,6 +84,7 @@ api.tld/random?view=json api.tld/votd?view=human api.tld/show?kw=john3:16,1john5:7&view=plain api.tld/search?kw=faith +api.tld/search?kw=nimrod&view=rich