149 lines
4.3 KiB
Python
149 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
The views
|
|
"""
|
|
import logging
|
|
import secrets
|
|
import string
|
|
from datetime import timedelta, datetime
|
|
|
|
from quart import Blueprint, redirect, request, flash, make_response, current_app, render_template
|
|
from pygments import highlight
|
|
from pygments.formatters.html import HtmlFormatter
|
|
from pygments.lexers import get_lexer_by_name, get_all_lexers
|
|
from sqlalchemy import or_
|
|
|
|
from stickynotes.db import session
|
|
from stickynotes.models import StickyNote
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
|
views = Blueprint('views', __name__)
|
|
|
|
|
|
EXPIRY_DELTAS = {
|
|
'10min': timedelta(minutes=10),
|
|
'1d': timedelta(days=1),
|
|
'1w': timedelta(days=7),
|
|
'2w': timedelta(days=14),
|
|
'1m': timedelta(days=30)
|
|
}
|
|
|
|
|
|
def _generate_short_url():
|
|
"""
|
|
Encode the URL
|
|
"""
|
|
alphabet = string.ascii_lowercase + string.digits
|
|
short_url = ''.join(secrets.choice(alphabet) for _ in range(8))
|
|
return short_url
|
|
|
|
|
|
@views.route('/', methods=['GET'])
|
|
async def index():
|
|
"""
|
|
Add a new sticky note
|
|
"""
|
|
all_lexers = [(lexer[1][0], lexer[0]) for lexer in get_all_lexers() if len(lexer) > 1 and len(lexer[1]) > 0]
|
|
all_lexers.sort(key=lambda x: x[1].lower())
|
|
recaptcha_site_key = current_app.config.get('RECAPTCHA_SITE_KEY')
|
|
return await render_template('index.html', lexers=all_lexers, recaptcha_site_key=recaptcha_site_key)
|
|
|
|
|
|
@views.route('/notes', methods=['GET'])
|
|
async def notes():
|
|
"""
|
|
Show a list of recent notes
|
|
"""
|
|
notes = StickyNote.query\
|
|
.filter(or_(StickyNote.expiry == None, StickyNote.expiry < datetime.utcnow()))\
|
|
.filter(~StickyNote.private)\
|
|
.order_by(StickyNote.created.desc())\
|
|
.limit(10) # noqa
|
|
return await render_template('notes.html', notes=notes)
|
|
|
|
|
|
@views.route('/about', methods=['GET'])
|
|
async def about():
|
|
"""
|
|
Show the about page
|
|
"""
|
|
return await render_template('about.html')
|
|
|
|
|
|
@views.route('/', methods=['POST'])
|
|
async def save():
|
|
"""
|
|
Save a sticky note
|
|
"""
|
|
form = await request.form
|
|
if form.get('computer') and form['computer'].lower() != 'no':
|
|
return redirect('/')
|
|
# Save the note
|
|
try:
|
|
created = datetime.utcnow()
|
|
expiry = created + EXPIRY_DELTAS.get(form['expiry'], EXPIRY_DELTAS['1d'])
|
|
# Generate a short url, and check if it exists in the db
|
|
url = _generate_short_url()
|
|
while StickyNote.query.filter(StickyNote.url == url).first():
|
|
url = _generate_short_url()
|
|
# Create a new note
|
|
note = StickyNote(
|
|
title=form.get('title', ''),
|
|
source=form['source'],
|
|
lexer=form['language'],
|
|
created=created,
|
|
expiry=expiry,
|
|
private=True,
|
|
url=url
|
|
)
|
|
session.add(note)
|
|
session.commit()
|
|
return redirect('/' + note.url)
|
|
except Exception as e:
|
|
flash(str(e), 'danger')
|
|
session.rollback()
|
|
return redirect('/')
|
|
|
|
|
|
@views.route('/<string:note_url>', methods=['GET'])
|
|
async def view(note_url):
|
|
"""
|
|
Show a sticky note
|
|
|
|
:param note_url: The note to show
|
|
"""
|
|
note = StickyNote.query.filter(StickyNote.url == note_url).first()
|
|
if not note:
|
|
flash('That note does not exist', 'danger')
|
|
return redirect('/')
|
|
|
|
lexer = get_lexer_by_name(note.lexer)
|
|
formatter = HtmlFormatter(linenos=True, cssclass='source')
|
|
result = highlight(note.source, lexer, formatter)
|
|
return await render_template('view.html', note=note, source=result)
|
|
|
|
|
|
@views.route('/raw/<string:note_url>', methods=['GET'])
|
|
async def raw(note_url):
|
|
"""
|
|
Show the raw version of a sticky note
|
|
|
|
:param note_url: The note to show
|
|
"""
|
|
note = StickyNote.query.filter(StickyNote.url == note_url).scalar()
|
|
if not note:
|
|
flash('That note does not exist', 'danger')
|
|
return redirect('/')
|
|
return await render_template('raw.html', source=note.source), 200, {'Content-Type': 'text/plain; charset=utf-8'}
|
|
|
|
|
|
@views.route('/pygments.css', methods=['GET'])
|
|
async def pygments_css():
|
|
"""
|
|
Return the Pygments CSS to the browser
|
|
"""
|
|
response = await make_response(HtmlFormatter(style='nord').get_style_defs())
|
|
response.headers['Content-Type'] = 'text/css'
|
|
return response
|