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
89 lines
2.7 KiB
Python
2 years 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)
|