diff --git a/app.py b/app.py
index df3809e..4656840 100644
--- a/app.py
+++ b/app.py
@@ -2,18 +2,11 @@
from flask import Flask, request, jsonify, send_file
import random
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
+import string # for literals
+DEBUG = 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
@@ -34,9 +27,9 @@ def dbg2(message):
dbg("Debug Level 1 Enabled")
dbg2("Debug Level 2 Enabled")
-kjv_db = sqlite3.connect("kjv.db")
-kjv_cur = kjv_db.cursor()
-verse_ids = [i[0] for i in kjv_cur.execute("SELECT id FROM t_kjv;").fetchall()]
+kjv_cur = sqlite3.connect("kjv.db").cursor()
+verse_ids = [i[0] for i in kjv_cur.execute("SELECT id FROM fts_kjv;").fetchall()]
+book_names = [i[0] for i in kjv_cur.execute("SELECT n FROM key_english").fetchall()]
app = Flask(__name__)
@@ -48,26 +41,182 @@ idx_text = 4
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())
+ return(kjv_cur.execute("SELECT * FROM fts_kjv WHERE id = {};".format(verse_id)).fetchone())
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]
+ result = kjv_cur.execute("SELECT n FROM key_english WHERE b = {};".format(book_id)).fetchone()
+ if result:
+ result = result[0]
dbg("lookup_bookname: {}".format(result))
return result
+def lookup_book_id(bookname):
+ dbg2("lookup_book_id({})".format(bookname))
+ result = kjv_cur.execute("SELECT b FROM key_english WHERE n = '{}';".format(bookname)).fetchone()
+ if result:
+ result = result[0]
+ return result
+
+def lookup_fts(kwds):
+ return kjv_cur.execute("SELECT * FROM fts_kjv('{}')".format(kwds)).fetchall()
def lookup_contains(kw):
- results = kjv_cur.execute("SELECT * FROM t_kjv WHERE t LIKE '%{}%';".format(kw)).fetchall()
+ results = kjv_cur.execute("SELECT * FROM fts_kjv WHERE t LIKE '%{}%';".format(kw)).fetchall()
dbg("lookup_contains({}) {} results".format(kw,len(results)))
return results
+def lookup_by_verse_id(start_verse, end_verse = None):
+ if not end_verse:
+ results = kjv_cur.execute("SELECT * FROM fts_kjv WHERE id = {};".format(start_verse)).fetchall()
+ else:
+ results = kjv_cur.execute("SELECT * FROM fts_kjv WHERE id BETWEEN {} AND {};".format(start_verse, end_verse)).fetchall()
+ return results
+
+
+def get_verse_id(book_id, chapter, verse):
+ # verse_id is 00000000 (00 000 000) (book + chapter + verse)
+ chapterid = chapter.zfill(3)
+ verseid = verse.zfill(3)
+ return str(book_id)+chapterid+verseid
+
+def check_lone_word(text, kw):
+ kw_length = len(kw)
+ kw_location = text.find(kw)
+ try:
+ if (text[kw_location-1]).isalpha():
+ return False
+ except IndexError:
+ # If it's an indexerror, it's likely that
+ # the keyword is at the end or beginning
+ # of the text.
+ pass
+ try:
+ if (text[kw_location+kw_length]).isalpha():
+ return False
+ except IndexError:
+ pass
+ return True
+
def lookup_contains_exact(kw):
- results = kjv_cur.execute("SELECT * FROM t_kjv WHERE t LIKE '%{}%';".format(kw)).fetchall()
+ preresult = lookup_contains(kw)
+ results = []
+ for result in preresult:
+ if check_lone_word(result[idx_text], kw):
+ results.append(result)
dbg("lookup_contains({}) {} results".format(kw,len(results)))
return results
+def ref_input_cleaning(ref, valid_chars=(string.ascii_letters + string.digits + ":-,")):
+ # removed invalid characters, whitespace
+ ref = list(ref.replace(" ",""))
+
+ # basic validation checks
+ # do we have a valid verse designator?
+ if ref.count(':') != 1:
+ return False
+ # are we only checking one range?
+ if ref.count("-") > 1:
+ return False
+ # does our argument end in a number or an endrange?
+ if not ref[-1].isdigit() and ref[-1] != '-':
+ return False
+
+
+ # preserve book number if we can guess the first
+ # character is a number and 3nd is a letter
+ if ref[0].isdigit() and ref[1].isalpha():
+ prefix = ref.pop(0) + " "
+ else:
+ prefix = ''
+
+ # clean the rest of the reference
+ cleaned_ref = []
+ for character in ref:
+ if character in valid_chars:
+ cleaned_ref.append(character)
+ # Was there a problem?
+ if len(cleaned_ref) == 0:
+ return False
+ return prefix + ''.join(cleaned_ref).capitalize()
+
+def search_input_cleaning(query, valid_chars=string.ascii_letters + string.digits + "+^\" "):
+ cleaned_query = []
+ for character in query:
+ if character in valid_chars:
+ cleaned_query.append(character)
+ return ''.join(cleaned_query)
+
+
+
+def ref_parse_book(ref):
+ for book in reversed(book_names):
+ if book.startswith(ref):
+ return book
+ return False
+
+@app.get("/show")
+def show():
+ ref = request.args.get("kw", "John 3:16")
+ dbg("show({})".format(ref))
+ ref = ref_input_cleaning(ref)
+ if not ref:
+ return("Invalid Query")
+ verse_results = []
+ #check if the search is for multiple refs
+ refs = ref.split(',')
+ for ref in refs:
+ dbg("show.reference({})".format(ref))
+
+ maybe_chapter = ref.split(':')[0][3:]
+ ref_chapter = ''
+ for maybedigit in maybe_chapter:
+ if maybedigit.isdigit():
+ ref_chapter += maybedigit
+
+ ref_verse = ref.split(':')[1]
+ if ref.__contains__('-'):
+ if ref.endswith('-'):
+ start_verse = ref_verse.split("-")[0]
+ end_verse = '500' # just get all the verses if it ends with a dash
+ else:
+ start_verse, end_verse = ref_verse.split("-")[0], ref_verse.split("-")[1]
+ else:
+ start_verse = ref_verse
+ end_verse = None
+ end_verse_id = None
+
+ book_str = ref_input_cleaning(ref, string.ascii_letters)
+ ref_bookname = ref_parse_book(book_str)
+ ref_book_id = lookup_book_id(ref_bookname)
+ if not ref_book_id:
+ return("Book reference invalid. Ex: 1John3:16")
+
+ start_verse_id = get_verse_id(ref_book_id, ref_chapter, start_verse)
+ if end_verse:
+ end_verse_id = get_verse_id(ref_book_id, ref_chapter, end_verse)
+
+ dbg2("show.start_verse_id({})".format(start_verse_id))
+ dbg2("show.end_verse_id({})".format(end_verse_id))
+ results = lookup_by_verse_id(start_verse_id, end_verse_id)
+ dbg2("show.results({})".format(results))
+
+ for result in results:
+ verse_results.append(result)
+
+ response_list = response_multi(verse_results)
+
+ arg_view = request.args.get("view", None)
+ if arg_view == "plain" or arg_view == "rich":
+ response = " No one is good enough to go to Heaven on their own merit. No matter how much good we do, we still come short. Romans 3:23(a) For all have sinned, and come short of the glory of God; Romans 3:10 As it is written, There is none righteous, no, not one: There is a payment for our sin, which is eternal death in a place called Hell and the Lake of Fire. Romans 6:23 For the wages of sin is death; but the gift of God is eternal life through Jesus Christ our Lord. Revelation 20:14 And death and hell were cast into the lake of fire. This is the second death. And whosoever was not found written in the book of life was cast into the lake of fire. Salvation is simply putting your faith (or believing) that Jesus Christ paid for your sins. Romans 5:8 But God commendeth his love toward us, in that, while we were yet sinners, Christ died for us. John 3:16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. 1 Corinthians 15:3-4 ...Christ died for our sins according to the scriptures; And that he was buried, and that he rose again the third day according to the scriptures: Eternal life is a gift purchased by the blood of Jesus and offered freely to those who call upon Him. Anyone who believes on the Lord Jesus Christ will be saved forever. Being saved is a one time event. Titus 1:2 In hope of eternal life, which God, that cannot lie, promised before the world began; John 3:15-16 For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life. When God saves you he gives you eternal life; in other words, life that will last forever. So, when he saves you, it is forever. No matter what you do after you receive “the gift of eternal life” it can never end. Otherwise God lied, and we know that God “cannot lie”. Romans 10:9-10 That if thou shalt confess with thy mouth the Lord Jesus, and shalt believe in thine heart that God hath raised him from the dead, thou shalt be saved. For with the heart man believeth unto righteousness; and with the mouth confession is made unto salvation. Let us help you word a prayer. Realize it is not mere words that save, but your faith in Jesus Christ. Dear Jesus, I know that I am a sinner, and I know I deserve to go to Hell. But I believe that you died on the cross, was buried, and rose from the grave to pay for my sins. Please save me and take me to Heaven when I die. Amen. URL Root: https://api.1611.social/ (you are here) '/someverse' accepts verse references in a variety of forms, including single verses and verse ranges. For
-example:
- Most recognizable abbreviations are allowed, and spelling errors are ignored if the book can be made
- out in the first few characters. No distinction is made between upper and lower case. Multiple
- references may be provided on an input line, delimited by spaces or commas.
- '/show?kw=' will try to match single verses and verse ranges. For example: '/s*/keyword' accepts a search word, and will return any verses matching the query '/search?kw=keyword' accepts a search word, and will return any verses matching the query. For example: If you want to put the verse of the day into your website, you can use the following example php:
".join(response_list)
+ else:
+ response = jsonify(response_list)
+
+ return response
+
+
def response_dict(scripture):
+ # used for JSON responses
verse = {
"bookname": lookup_bookname(scripture[idx_book]),
"chapter": scripture[idx_chapter],
@@ -86,7 +235,7 @@ def response_text(scripture):
def response_rich(scripture):
css = open('human_readable.css', 'r')
response_html = open('response.html', 'r')
- # passage, text
+ # (passage, text) is the html formatting arguments
bookname = lookup_bookname(scripture[idx_book])
chapter = str(scripture[idx_chapter])
@@ -99,7 +248,7 @@ def response_rich(scripture):
def response_single(scripture):
dbg2("response_single({})".format(scripture))
- arg_view = request.args.get("view", None)
+ arg_view = request.args.get("view", 'json')
dbg("->requested_format = {}".format(arg_view))
if arg_view == "plain":
return(response_text(scripture))
@@ -112,20 +261,17 @@ def response_single(scripture):
def response_multi(scriptures):
dbg2("response_multi({})".format(scriptures))
response = []
- arg_view = request.args.get("view", None)
+ arg_view = request.args.get("view", 'json')
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)
@@ -146,6 +292,10 @@ def page_not_found(e):
def idx():
return send_file("index.html")
+@app.get("/salvation")
+def salvation():
+ return send_file("heaven.html")
+
#backwards-compatibility
@app.get('/t/random', defaults={'view':'plain'})
@app.get('/random')
@@ -164,51 +314,18 @@ def verse_of_the_day():
scripture = lookup_one_verse(random.choice(verse_ids))
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:
+ cleaned_keywords = search_input_cleaning(keywords)
+ if not cleaned_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)
-
+ results = lookup_fts(cleaned_keywords)
response_list = response_multi(results)
arg_view = request.args.get("view", None)
@@ -219,128 +336,3 @@ def search():
dbg2("Search Response: {}".format(response))
return response
-
-
-@app.get("/qwerty")
-def test():
- style = css.read()
- return (style + "Hello! Testing!")
-
-# plain
-@app.get("/
'.join(map(str, result))
- return result
- except Exception as e:
- return str(e)
-
-#search text json
-@app.get("/sl/
'.join(map(str, complete_result))
- return result
- except Exception as e:
- return str(e)
-
-#search pretty multiple
-@app.get("/splm/
'.join(map(str, complete_result))
- return result
- except Exception as e:
- return str(e)
diff --git a/heaven.html b/heaven.html
new file mode 100644
index 0000000..c910998
--- /dev/null
+++ b/heaven.html
@@ -0,0 +1,30 @@
+1. Understand you are a sinner:
+2. Realize the penalty for your sin.
+3. Believe that Christ died, was buried and rose from the grave as a payment for your sin.
+4. Understand that salvation will last forever.
+5. Pray and ask Jesus Christ to save you.
+Usage
-
Verse searching
-
+
+/search?kw=john3:16
+/search?kw=John 3:13-18
+/search?kw=2 Peter 2:8
+/search?kw=1 John 3:3- (gets the whole rest of the chapter)
+/search?kw=ecc 2:1-
+
+Keyword searching
-
+
+
+
+Integration
-FUTURE ENDPOINT SPECIFICATION
-======================
+API ENDPOINT SPECIFICATION v 0.2
+================================
/random - outputs a random verse
/votd - returns verse of the day
@@ -68,20 +69,10 @@ 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
-
EXAMPLES
========
-api.tld/random?view=json
-api.tld/votd?view=human
+api.tld/random
+api.tld/votd?view=rich
api.tld/show?kw=john3:16,1john5:7&view=plain
api.tld/search?kw=faith
api.tld/search?kw=nimrod&view=rich
diff --git a/kjv.db b/kjv.db
index 12f606b..0420c5f 100644
Binary files a/kjv.db and b/kjv.db differ