You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.7 KiB
Python

1 year ago
from sqlalchemy import create_engine
from sqlalchemy.sql import select, update, insert
from sqlalchemy.sql.expression import literal
from .schema import metadata, articles
from markdown import markdown
from string import whitespace, punctuation
import re
import os
import sys
db_file = os.path.join(sys.argv[1], 'lazy_wiki.sqlite3')
regex = re.compile(r'^\W+|^\W*\w+\W*')
# instantiate an engine for connecting to a database
engine = create_engine('sqlite:///{}'.format(db_file))
# create tables if they don't exist
metadata.create_all(engine)
# connect to the database
dbc = engine.connect()
def select_longest_keyword_string_starts_with(string):
'''
Fetch the longest keyword that the given string starts with.
'''
query = select([articles]) \
.where(literal(string).ilike(articles.c.title + '%'))
# may be bottleneck
results = [dict(u) for u in dbc.execute(query).fetchall()]
if not results:
return None
return max(results, key = lambda keyword : len(keyword['title']))
def select_article(keyword):
'''
Fetch an article associated with the given keyword.
'''
query = select([articles]) \
.where(articles.c.title == literal(keyword))
try:
return dict(dbc.execute(query).fetchone())
except:
return None
def select_formatted_article(keyword):
'''
Fetch an article associated with the given keyword,
add hyperlinks to it, and format it to HTML.
'''
# get article content
article = select_article(keyword)
raw = article['content']
# add hyperlinks to the content
formatted = ''
# until the raw content is empty
while raw:
# if the remaining raw content starts with a keyword
word = select_longest_keyword_string_starts_with(raw)
if word and raw[len(word['title'])] in punctuation + whitespace:
# use original capitalization for hyperlink text
original = raw[:len(word['title'])]
# create a Markdown hyperlink
word = '[{}](/view/{})'.format(original, word['title'])
# cut off the start of the raw content
raw = raw[len(original):]
else:
# cut a word off the start of the raw content
word = regex.search(raw).group()
raw = raw[len(word):]
# add the hyperlink or word to the formatted content
formatted += word
article['content'] = markdown(formatted)
return article
def insert_article(**kwargs):
query = insert(articles).values(**kwargs)
dbc.execute(query)
def update_article(title, **kwargs):
query = update(articles) \
.where(articles.c.title == literal(title)) \
.values(**kwargs)
dbc.execute(query)