# -*- coding: utf-8 -*- """ The views """ import logging from datetime import timedelta, datetime import requests import short_url from flask 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 _is_recaptcha_valid(secret, response, remote_ip=None): """ POST to the recaptcha service to check if the recaptcha is valid """ data = {'secret': secret, 'response': response} if remote_ip: data['remoteip'] = remote_ip response = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data) try: json_response = response.json() return json_response['success'] except ValueError: return False @views.route('/', methods=['GET']) 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 render_template('index.html', lexers=all_lexers, recaptcha_site_key=recaptcha_site_key) @views.route('/notes', methods=['GET']) def notes(): """ Show a list of recent notes """ recent_notes = StickyNote.query\ .filter(or_(StickyNote.expiry == None, StickyNote.expiry < datetime.utcnow()))\ .filter(~StickyNote.private)\ .order_by(StickyNote.created.desc())\ .limit(10) # noqa return render_template('notes.html', recent=recent_notes) @views.route('/about', methods=['GET']) def about(): """ Show the about page """ return render_template('about.html') @views.route('/', methods=['POST']) def save(): """ Save a sticky note """ # Check if the recaptcha is valid recaptcha_secret_key = current_app.config.get('RECAPTCHA_SECRET_KEY') if recaptcha_secret_key: is_recaptcha_valid = False try: is_recaptcha_valid = _is_recaptcha_valid(recaptcha_secret_key, request.form['g-recaptcha-response']) except KeyError: flash('Unable to verify you, don\'t forget to complete the captcha.', 'danger') print('No form variable') else: is_recaptcha_valid = True if not is_recaptcha_valid: return redirect('/') # Save the note try: created = datetime.utcnow() expiry = EXPIRY_DELTAS.get(request.form['expiry']) if expiry: expiry = created + expiry source = request.form['source'] lexer = request.form['language'] title = request.form.get('title', '') private = True if request.form.get('private') else False string_id = ''.join([source, lexer, title, created.isoformat()]) url = short_url.encode_url(sum([ord(char) for char in string_id]), min_length=8) note = StickyNote( title=title, source=source, lexer=lexer, created=created, expiry=expiry, private=private, 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']) def view(note_url): """ Show 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('/') lexer = get_lexer_by_name(note.lexer) formatter = HtmlFormatter(linenos=True, cssclass='source') result = highlight(note.source, lexer, formatter) return render_template('view.html', note=note, source=result) @views.route('/raw/', methods=['GET']) 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 render_template('raw.html', source=note.source), 200, {'Content-Type': 'text/plain; charset=utf-8'} @views.route('/pygments.css', methods=['GET']) def pygments_css(): """ Return the Pygments CSS to the browser """ response = make_response(HtmlFormatter(style='nord').get_style_defs()) response.headers['Content-Type'] = 'text/css' return response