# -*- 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: E711 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('/', 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/', 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