Shortcode backend

This commit is contained in:
2023-05-30 23:12:28 -07:00
parent e9258c34f6
commit fc778a33dd
2 changed files with 50 additions and 9 deletions
+49 -8
View File
@@ -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,6 +626,41 @@ 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.")
+1 -1
View File
@@ -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: