Shortcode backend
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
# app.py
|
# app.py
|
||||||
from flask import Flask, request, jsonify, send_file, render_template
|
from flask import Flask, request, jsonify, send_file, render_template, redirect
|
||||||
import random
|
import random
|
||||||
from datetime import date, datetime, timedelta # used for daily verse
|
from datetime import date, datetime, timedelta # used for daily verse
|
||||||
import sqlite3
|
import sqlite3
|
||||||
@@ -40,6 +40,7 @@ Bible Reading Plan
|
|||||||
/seq Wrap back to Gen 1:1 when you reach the end of Rev
|
/seq Wrap back to Gen 1:1 when you reach the end of Rev
|
||||||
/seq Querying what your UID's next verse is going to be
|
/seq Querying what your UID's next verse is going to be
|
||||||
https://docs.python.org/3/library/sqlite3.html#sqlite3-placeholders
|
https://docs.python.org/3/library/sqlite3.html#sqlite3-placeholders
|
||||||
|
URL Shortener for sharing groups of scripture.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -74,12 +75,11 @@ cached: dict = {
|
|||||||
]
|
]
|
||||||
cached["chapter_list"].sort()
|
cached["chapter_list"].sort()
|
||||||
|
|
||||||
def int32_to_id(n):
|
def generate_short_id():
|
||||||
if n==0: return "0"
|
remain = random.randrange(614_656,17_210_367) # resolves to length of 5
|
||||||
chars="0123456789ACEFHJKLMNPRTUVWXY"
|
chars="0123456789ACEFHJKLMNPRTUVWXY"
|
||||||
length=len(chars)
|
length=len(chars)
|
||||||
result=""
|
result=""
|
||||||
remain=n
|
|
||||||
while remain>0:
|
while remain>0:
|
||||||
pos = remain % length
|
pos = remain % length
|
||||||
remain = remain // length
|
remain = remain // length
|
||||||
@@ -187,8 +187,9 @@ def ref_input_cleaning(
|
|||||||
else:
|
else:
|
||||||
return "".join(cleaned_ref)
|
return "".join(cleaned_ref)
|
||||||
def search_input_cleaning(
|
def search_input_cleaning(
|
||||||
query, valid_chars=string.ascii_letters + string.digits + '+^"* '
|
query, valid_chars=string.ascii_letters + string.digits + '+^* '
|
||||||
):
|
):
|
||||||
|
# should protect against SQL injection, maybe. Should have another person review.
|
||||||
cleaned_query = []
|
cleaned_query = []
|
||||||
for character in query:
|
for character in query:
|
||||||
if character in valid_chars:
|
if character in valid_chars:
|
||||||
@@ -200,8 +201,10 @@ def ref_parse_book(ref):
|
|||||||
return book
|
return book
|
||||||
return False
|
return False
|
||||||
@app.get("/find")
|
@app.get("/find")
|
||||||
def parse_query():
|
def parse_query(query_override:str = None):
|
||||||
query = request.args.get("kw", None)
|
query = request.args.get("kw", None)
|
||||||
|
if query_override:
|
||||||
|
query = query_override
|
||||||
if query:
|
if query:
|
||||||
query = query.strip()
|
query = query.strip()
|
||||||
logging.info(f"Query: {query}")
|
logging.info(f"Query: {query}")
|
||||||
@@ -423,9 +426,12 @@ def page_not_found(e):
|
|||||||
}
|
}
|
||||||
return jsonify(message)
|
return jsonify(message)
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
def idx():
|
@app.get("/<shortcode>")
|
||||||
|
def idx(shortcode=''):
|
||||||
if not sanity:
|
if not sanity:
|
||||||
return("There is an issue with permissions. Check log, or please notify tyler@dinsmoor.us")
|
return("There is an issue with permissions. Check log, or please notify tyler@dinsmoor.us")
|
||||||
|
if shortcode:
|
||||||
|
return resolve_shortcode(shortcode)
|
||||||
logging.info("Index Served")
|
logging.info("Index Served")
|
||||||
return send_file("html/index.html")
|
return send_file("html/index.html")
|
||||||
@app.get("/salvation")
|
@app.get("/salvation")
|
||||||
@@ -572,7 +578,7 @@ def sequential_read(start=0, num=1, uid=None, getuid=False):
|
|||||||
start = cached["verse_ids"].index(
|
start = cached["verse_ids"].index(
|
||||||
int(show(kw=start, get_start_verse_id=True))
|
int(show(kw=start, get_start_verse_id=True))
|
||||||
)
|
)
|
||||||
uid = int32_to_id(random.randrange(614_656,17_210_367)) # range returns a 5 digit id
|
uid = generate_short_id() # range returns a 5 digit id
|
||||||
try:
|
try:
|
||||||
seq_cur.execute(
|
seq_cur.execute(
|
||||||
f"INSERT INTO reading_tracker VALUES('{uid}', {start}, '{last_used}')"
|
f"INSERT INTO reading_tracker VALUES('{uid}', {start}, '{last_used}')"
|
||||||
@@ -620,7 +626,42 @@ def sequential_read(start=0, num=1, uid=None, getuid=False):
|
|||||||
response = jsonify(response_list)
|
response = jsonify(response_list)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
@app.get("/mksc/<query>")
|
||||||
|
def generate_shortcode(query: str = ""):
|
||||||
|
query = search_input_cleaning(query)
|
||||||
|
if not query:
|
||||||
|
return("Empty query.")
|
||||||
|
if usermode == "Single":
|
||||||
|
short_conn = sqlite3.connect("data/shortcodes.db", check_same_thread=False)
|
||||||
|
else:
|
||||||
|
short_conn = sqlite3.connect("data/shortcodes.db")
|
||||||
|
short_cur = short_conn.cursor()
|
||||||
|
short_cur.execute("CREATE TABLE IF NOT EXISTS shortcodes (shortcode TEXT PRIMARY KEY, query TEXT UNIQUE, creation_date TEXT)")
|
||||||
|
short_conn.commit()
|
||||||
|
creation_date = str(datetime.now())
|
||||||
|
shortcode = generate_short_id()
|
||||||
|
short_cur.execute(
|
||||||
|
f"REPLACE INTO shortcodes(shortcode,query,creation_date) VALUES('{shortcode}', '{query}', '{creation_date}')"
|
||||||
|
)
|
||||||
|
short_conn.commit()
|
||||||
|
short_cur.close()
|
||||||
|
logging.info(f"Generated Shortcode {shortcode} for query '{query}'")
|
||||||
|
return shortcode
|
||||||
|
def resolve_shortcode(shortcode: str = ""):
|
||||||
|
shortcode = search_input_cleaning(shortcode, valid_chars="0123456789ACEFHJKLMNPRTUVWXY")
|
||||||
|
if not shortcode:
|
||||||
|
return("Empty shortcode.")
|
||||||
|
if usermode == "Single":
|
||||||
|
short_conn = sqlite3.connect("data/shortcodes.db", check_same_thread=False)
|
||||||
|
else:
|
||||||
|
short_conn = sqlite3.connect("data/shortcodes.db")
|
||||||
|
short_cur = short_conn.cursor()
|
||||||
|
query = short_cur.execute(f"SELECT query FROM shortcodes WHERE shortcode = '{shortcode}'").fetchone()[0]
|
||||||
|
short_cur.close()
|
||||||
|
logging.info(f"Resolved Shortcode {shortcode} for query '{query}'")
|
||||||
|
|
||||||
|
return redirect(f"/find?kw={query}&view=rich")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
print("You must run this program within a uwsgi environment if you are running this for multiple users.")
|
print("You must run this program within a uwsgi environment if you are running this for multiple users.")
|
||||||
print("Otherwise, you may end up with database corruption if multiple writes happen.")
|
print("Otherwise, you may end up with database corruption if multiple writes happen.")
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
from os import stat, getuid
|
from os import stat, getuid
|
||||||
|
|
||||||
def check_sanity():
|
def check_sanity():
|
||||||
dependancies = ['data/seq.db']
|
dependancies = ['data/seq.db', "data/shortcodes.db"]
|
||||||
current_uid = getuid()
|
current_uid = getuid()
|
||||||
for dependancy in dependancies:
|
for dependancy in dependancies:
|
||||||
if stat(dependancy).st_uid != current_uid:
|
if stat(dependancy).st_uid != current_uid:
|
||||||
|
|||||||
Reference in New Issue
Block a user