codesmidgen/stickynotes/views.py

167 lines
5.0 KiB
Python

# -*- coding: utf-8 -*-
"""
The views
"""
from datetime import timedelta, datetime
import logging
from flask import Blueprint, redirect, request, flash, make_response, current_app
from flask.ext.mako import 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_
import requests
import short_url
from models import StickyNote, get_session
log = logging.getLogger(__name__)
views = Blueprint(u'views', __name__)
EXPIRY_DELTAS = {
u'10min': timedelta(minutes=10),
u'1d': timedelta(days=1),
u'1w': timedelta(days=7),
u'2w': timedelta(days=14),
u'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 = {u'secret': secret, u'response': response}
if remote_ip:
data[u'remoteip'] = remote_ip
response = requests.post(u'https://www.google.com/recaptcha/api/siteverify', data=data)
try:
json_response = response.json()
print(json_response)
return json_response[u'success']
except ValueError:
print response
return False
@views.route('/', methods=[u'GET'])
def index():
"""
Add a new sticky note
"""
all_lexers = [(lexer[1][0], lexer[0]) for lexer in get_all_lexers()]
all_lexers.sort(key=lambda x: x[1].lower())
now = datetime.utcnow()
recaptcha_site_key = current_app.config.get(u'RECAPTCHA_SITE_KEY')
return render_template(u'index.mako', lexers=all_lexers, recaptcha_site_key=recaptcha_site_key)
@views.route('/notes', methods=[u'GET'])
def notes():
"""
Show a list of recent notes
"""
recent_notes = get_session().query(StickyNote)\
.filter(or_(StickyNote.expiry == None, StickyNote.expiry < now))\
.filter(~StickyNote.private)\
.order_by(StickyNote.created.desc())\
.limit(10)
return render_template(u'notes.mako', recent=recent_notes)
@views.route('/about', methods=[u'GET'])
def about():
"""
Show the about page
"""
return render_template(u'about.mako')
@views.route('/save', methods=[u'POST'])
def save():
"""
Save a sticky note
"""
# Check if the recaptcha is valid
recaptcha_secret_key = current_app.config.get(u'RECAPTCHA_SECRET_KEY')
is_recaptcha_valid = False
try:
is_recaptcha_valid = _is_recaptcha_valid(recaptcha_secret_key, request.form[u'g-recaptcha-response'])
except KeyError:
flash(u'Unable to verify you, don\'t forget to complete the captcha.', u'danger')
print(u'No form variable')
if not is_recaptcha_valid:
return redirect(u'/')
# Save the note
db_session = get_session()
try:
created = datetime.utcnow()
expiry = EXPIRY_DELTAS.get(request.form[u'expiry'])
if expiry:
expiry = created + expiry
source = request.form[u'source']
lexer = request.form[u'language']
title = request.form.get(u'title', u'')
private = True if request.form.get(u'private') else False
string_id = u''.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
)
db_session.add(note)
db_session.commit()
return redirect(u'/' + note.url)
except Exception as e:
flash(str(e), 'danger')
db_session.rollback()
return redirect(u'/')
@views.route('/<string:note_url>', methods=[u'GET'])
def view(note_url):
"""
Show a sticky note
:param note_url: The note to show
"""
note = get_session().query(StickyNote).filter(StickyNote.url == note_url).scalar()
if not note:
flash(u'That note does not exist', 'danger')
return redirect(u'/')
lexer = get_lexer_by_name(note.lexer)
formatter = HtmlFormatter(linenos=True, cssclass=u'source')
result = highlight(note.source, lexer, formatter)
return render_template(u'view.mako', note=note, source=result)
@views.route('/raw/<string:note_url>', methods=[u'GET'])
def raw(note_url):
"""
Show the raw version of a sticky note
:param note_url: The note to show
"""
note = get_session().query(StickyNote).filter(StickyNote.url == note_url).scalar()
if not note:
flash(u'That note does not exist', 'danger')
return redirect(u'/')
return render_template(u'raw.mako', source=note.source), 200, {'Content-Type': 'text/plain; charset=utf-8'}
@views.route(u'/pygments.css', methods=[u'GET'])
def pygments_css():
"""
Return the Pygments CSS to the browser
"""
response = make_response(HtmlFormatter().get_style_defs())
response.headers['Content-Type'] = 'text/css'
return response