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,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.")
+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: