Added sequential iteration feature with persistant uid

This commit is contained in:
2023-01-21 23:49:46 -08:00
parent f629835961
commit 2610bf5347
4 changed files with 168 additions and 17 deletions
+92 -11
View File
@@ -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
View File
Binary file not shown.
+34 -4
View File
@@ -5,7 +5,11 @@
<style>
html{
font-family: sans-serif;
font-size: 14pt;
width: 768px;
}
a {
color: #547720
}
</style>
</head>
@@ -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
===========
+40
View File
@@ -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>