Added sequential iteration feature with persistant uid
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
# app.py
|
||||
from flask import Flask, request, jsonify, send_file
|
||||
import random
|
||||
from datetime import date # used for daily verse
|
||||
from datetime import date, datetime # used for daily verse
|
||||
import sqlite3
|
||||
import string # for literals
|
||||
import json # for dictionary
|
||||
import hunspell # for spell checking
|
||||
|
||||
DEBUG = 0
|
||||
DEBUG = 2
|
||||
|
||||
"""
|
||||
To-do:
|
||||
@@ -19,7 +19,6 @@ Styles
|
||||
Bible Reading Plan
|
||||
Bible Reader
|
||||
Rich: <hr> on each comma
|
||||
find: handle ending with :
|
||||
find: handle ending with ,
|
||||
"""
|
||||
|
||||
@@ -71,7 +70,7 @@ def lookup_bookname(book_id):
|
||||
).fetchone()
|
||||
if result:
|
||||
result = result[0]
|
||||
dbg2("lookup_bookname.result = '{}'".format(result))
|
||||
dbg3("lookup_bookname.result = '{}'".format(result))
|
||||
return result
|
||||
|
||||
|
||||
@@ -149,23 +148,27 @@ def lookup_contains_exact(kw):
|
||||
return results
|
||||
|
||||
|
||||
def ref_input_cleaning(ref, valid_chars=(string.ascii_letters + string.digits + ":-,")):
|
||||
dbg2("ref_input_cleaning({})".format(ref))
|
||||
def ref_input_cleaning(
|
||||
ref, valid_chars=(string.ascii_letters + string.digits + ":-,"), ref_search=True
|
||||
):
|
||||
dbg3("ref_input_cleaning({})".format(ref))
|
||||
ref = ref.replace(" ", "")
|
||||
if ref.count(":") != 1:
|
||||
if ref.count(":") != 1 and ref_search:
|
||||
dbg2("ref_input_cleaning.if ref.count(:): TRUE")
|
||||
dbg2(" -> Assuming user wanted entire chapter")
|
||||
ref += ":-"
|
||||
if ref.count("-") > 1:
|
||||
if ref.endswith(":"):
|
||||
ref += "-"
|
||||
if ref.count("-") > 1 and ref_search:
|
||||
dbg2("ref_input_cleaning.if ref.count(-): TRUE")
|
||||
return False
|
||||
if not ref[-1].isdigit() and ref[-1] != "-":
|
||||
if not ref[-1].isdigit() and ref[-1] != "-" and ref_search:
|
||||
dbg2("ref_input_cleaning.if ref[-1] TRUE")
|
||||
return False
|
||||
ref = list(ref)
|
||||
# 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():
|
||||
if ref[0].isdigit() and ref[1].isalpha() and ref_search:
|
||||
prefix = ref.pop(0) + " "
|
||||
else:
|
||||
prefix = ""
|
||||
@@ -177,7 +180,10 @@ def ref_input_cleaning(ref, valid_chars=(string.ascii_letters + string.digits +
|
||||
# Was there a problem?
|
||||
if len(cleaned_ref) == 0:
|
||||
return False
|
||||
if ref_search:
|
||||
return prefix + "".join(cleaned_ref).capitalize()
|
||||
else:
|
||||
return "".join(cleaned_ref)
|
||||
|
||||
|
||||
def search_input_cleaning(
|
||||
@@ -271,8 +277,10 @@ def return_dict_rich(ref, defs):
|
||||
|
||||
|
||||
@app.get("/show")
|
||||
def show():
|
||||
def show(kw=None, get_start_verse_id=False):
|
||||
ref = request.args.get("kw", None)
|
||||
if kw:
|
||||
ref = kw
|
||||
if ref is None:
|
||||
return send_file("html/show.html")
|
||||
dbg("show({})".format(ref))
|
||||
@@ -312,6 +320,8 @@ def show():
|
||||
if not ref_book_id:
|
||||
return "Invalid Query"
|
||||
start_verse_id = get_verse_id(ref_book_id, ref_chapter, start_verse)
|
||||
if get_start_verse_id:
|
||||
return start_verse_id
|
||||
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))
|
||||
@@ -480,3 +490,74 @@ def reading_plan():
|
||||
# should default to the entire Bible in 1 year.
|
||||
# should start today() and end today()+1year
|
||||
# Should return a calender with date and verse range.
|
||||
|
||||
|
||||
@app.get("/seq")
|
||||
def sequential_read(start=0, num=1, uid=None, getuid=False):
|
||||
# /seq?uid=1
|
||||
uid = request.args.get("uid", uid)
|
||||
getuid = request.args.get("getuid", getuid)
|
||||
start = request.args.get("start", start)
|
||||
try:
|
||||
num = int(request.args.get("num", num))
|
||||
except ValueError:
|
||||
return "Invalid num argument"
|
||||
if not uid or not getuid:
|
||||
return send_file("html/seq.html")
|
||||
seq_conn = sqlite3.connect("data/seq.db")
|
||||
seq_cur = seq_conn.cursor()
|
||||
last_used = str(datetime.now())
|
||||
num -= 1 # 0 will mean "next"
|
||||
if num < 0:
|
||||
return jsonify({"error":"You may only increment forward."})
|
||||
|
||||
if getuid:
|
||||
import uuid
|
||||
|
||||
if start:
|
||||
start = verse_ids.index(int(show(kw=start, get_start_verse_id=True)))
|
||||
uid = str(uuid.uuid4())
|
||||
seq_cur.execute(
|
||||
"INSERT INTO reading_tracker VALUES('{}', {}, '{}')".format(
|
||||
uid, start, last_used
|
||||
)
|
||||
)
|
||||
seq_conn.commit()
|
||||
dbg2("Created new UID: {}".format(uid))
|
||||
return "Your new UID is: {}".format(uid)
|
||||
uid = ref_input_cleaning(uid, ref_search=False)
|
||||
try:
|
||||
nextverse = seq_cur.execute(
|
||||
"SELECT verse FROM reading_tracker WHERE uid = '{}'".format(uid)
|
||||
).fetchone()[0]
|
||||
dbg2("Queried UID {} on verse {}".format(uid, nextverse))
|
||||
except TypeError:
|
||||
dbg2("Invalid UID {}".format(uid))
|
||||
return jsonify({"error":"UID Invalid or purged"})
|
||||
if len(verse_ids) < (nextverse + num):
|
||||
# Correct our range to go to ceiling to prevent IndexError
|
||||
diff = len(verse_ids) - (nextverse + num)
|
||||
num = diff - num
|
||||
start_verse = verse_ids[nextverse]
|
||||
end_verse = verse_ids[nextverse + num]
|
||||
result_list = lookup_by_verse_id(start_verse, end_verse)
|
||||
response_list = response_multi(result_list)
|
||||
|
||||
dbg2(
|
||||
"SQL : UPDATE reading_tracker SET verse = {}, last_used = '{}' WHERE uid = '{}'".format(
|
||||
nextverse + num, last_used, uid
|
||||
)
|
||||
)
|
||||
seq_cur.execute(
|
||||
"UPDATE reading_tracker SET verse = {}, last_used = '{}' WHERE uid = '{}'".format(
|
||||
nextverse + num + 1, last_used, uid
|
||||
)
|
||||
)
|
||||
seq_conn.commit()
|
||||
arg_view = request.args.get("view", None)
|
||||
if arg_view == "plain" or arg_view == "rich":
|
||||
response = "<br>".join(response_list)
|
||||
else:
|
||||
response = jsonify(response_list)
|
||||
|
||||
return response
|
||||
|
||||
BIN
Binary file not shown.
+35
-5
@@ -5,10 +5,14 @@
|
||||
<style>
|
||||
html{
|
||||
font-family: sans-serif;
|
||||
font-size: 14pt;
|
||||
width: 768px;
|
||||
}
|
||||
a {
|
||||
color: #547720
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
</head>
|
||||
|
||||
<h1>KJV API</h1>
|
||||
<p>KJV accessible via web calls</p>
|
||||
@@ -38,17 +42,41 @@ API ENDPOINT SPECIFICATION v 0.3
|
||||
<a href="/search">/search</a> - returns a keyword search result set
|
||||
<a href="/show">/show</a> - returns a verse or set of verses by name/location
|
||||
<a href="/define">/define</a> - 1828 Noah Webster dictionary search
|
||||
<a href="/seq">/seq</a> - Incremental sequence of Bible verses (per request)
|
||||
|
||||
URL PARAMETERS
|
||||
==============
|
||||
?view=
|
||||
view=
|
||||
- json - json-encoded response
|
||||
- plain - plaintext response
|
||||
- rich - pretty response with css
|
||||
default: json
|
||||
|
||||
?kw=
|
||||
- The keyword(s) of your query.
|
||||
kw=
|
||||
- Used with /search /show/ /define /find
|
||||
- The keyword(s) of your query, separated by commas
|
||||
-- ex ?kw=1cor5:1-5,2Peter2:5
|
||||
|
||||
getuid=
|
||||
- Used only with /seq
|
||||
- Set this to "true" to recieve a new UID for use with /seq?uid=
|
||||
|
||||
start=
|
||||
- Used only with /seq
|
||||
- You can use a ref like "1Cor5:1" to start there
|
||||
instead of Genesis 1:1 as is the default
|
||||
- Only used when creating a new UID
|
||||
- If you want to "start in a new place" - just create a new UID
|
||||
|
||||
uid=
|
||||
- Used only with /seq
|
||||
- Required parameter for normal use of /seq
|
||||
|
||||
num=
|
||||
- Used only with /seq
|
||||
- You can get the "next # verses" in your sequence
|
||||
|
||||
|
||||
|
||||
|
||||
FEATURES
|
||||
@@ -56,7 +84,6 @@ FEATURES
|
||||
- King James Only. (No heretical commentaries or false Bibles)
|
||||
- High quality source documents
|
||||
- Free
|
||||
-
|
||||
- Developer hates the sodomites
|
||||
|
||||
INTERACTIVE ENDPOINTS
|
||||
@@ -77,6 +104,9 @@ api.tld/show?kw=john3:16,1john5:7&view=plain
|
||||
api.tld/search?kw=faith
|
||||
api.tld/search?kw=nimrod&view=rich
|
||||
api.tld/define?kw=faith&view=rich
|
||||
api.tld/define?kw=faith&view=rich
|
||||
api.tld/seq?getuid=true&start=2peter2:1
|
||||
api.tld/seq?uid=075a8496-9af7-4f44-84ec-ba3e7fa6de29&view=rich
|
||||
|
||||
INTEGRATION
|
||||
===========
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<header>
|
||||
<a href="/">Home</a> | <a href="/find">Quick Search</a> |
|
||||
<a href="/random?view=rich">Random Verse</a> |
|
||||
<a href="/votd?view=rich">Verse of the Day</a></header>
|
||||
|
||||
<h2>Sequential Bible Viewer</h2>
|
||||
<p>In order to use this, you first need a UID, which you
|
||||
can get by querying /seq?getuid=true and optionally include
|
||||
&start=BIBLEREF (where BIBLEREF is like 1Cor2:1) to set
|
||||
a start position other than Genesis 1:1.</p>
|
||||
|
||||
<p>After you have your UID, this will keep track of where you
|
||||
are at. Query /seq?uid=YOURUID and optionally include
|
||||
&num=# (where # is an integer of how many verses you want to
|
||||
include from your current position at a time)</p>
|
||||
|
||||
<p>The &view= argument works with this.<p>
|
||||
|
||||
<h4>Example Pleroma Bot shell script</h4>
|
||||
<pre>
|
||||
<code>
|
||||
#!/bin/sh
|
||||
verse=$(curl -XGET https://api.1611.social/seq?uid=MYUID?view=plain);
|
||||
curl -XPOST -u biblebot:MYPASSWORD \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"status": "'"${verse}"'"}' \
|
||||
https://my.fediverse.tld/api/v1/statuses;
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<style>
|
||||
html{
|
||||
font-family: sans-serif;
|
||||
font-size: 14pt;
|
||||
width: 768px;
|
||||
}
|
||||
a {
|
||||
color: #547720
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user