A full featured blog in RiotJS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.0 KiB

#! /usr/bin/python3
8 years ago
from functools import partial
from collections import defaultdict
from os import environ
8 years ago
from flask import abort, Flask, render_template, flash, request, send_from_directory, jsonify, g
from werkzeug.local import Local, LocalProxy, LocalManager
8 years ago
from flask_appconfig import AppConfig
from flask_login import LoginManager, login_required, login_user
from flask_wtf.csrf import CSRFProtect
from flask.ext.cache import Cache
8 years ago
from urllib.parse import unquote
from urllib.parse import quote, unquote
8 years ago
from json import dumps, loads
from admin import Admin
8 years ago
from werkzeug.contrib.cache import MemcachedCache
from posts import Posts
from projects import getProjects
memcache = MemcachedCache(['127.0.0.1:11211'])
cache = Cache(config={'CACHE_TYPE': 'memcached'})
login_manager = LoginManager()
8 years ago
def cacheit(key, thunk):
"""
Explicit memcached caching
8 years ago
"""
cached = memcache.get(quote(key))
8 years ago
if cached is None:
7 years ago
print("cache miss for %s" % key)
result = thunk()
memcache.set(quote(key), result)
8 years ago
return result
7 years ago
print("cache hit for %s" % key)
8 years ago
return cached
def get_posts():
posts = getattr(g, "posts", None)
if posts is None:
7 years ago
posts = g._posts = Posts(app.config["COUCHDB_USER"],
app.config["COUCHDB_PASSWORD"])
return posts
7 years ago
def get_initial():
initial_post = getattr(g, "initial_post", None)
if initial_post is None:
initial_post = g._initial_post = posts.getinitial()
return initial_post
8 years ago
def NeverWhere(configfile=None):
8 years ago
app = Flask(__name__)
app.config["TEMPLATES_AUTO_RELOAD"] = True
app.config["COUCHDB_SERVER"] = "http://localhost:5984"
app.config["COUCHDB_DATABASE"] = "blog"
8 years ago
#def favicon():
#return send_from_directory("/srv/http/goal/favicon.ico",
#'favicon.ico', mimetype='image/vnd.microsoft.icon')
print(environ["RIOTBLOG_SETTINGS"])
app.config.from_envvar('RIOTBLOG_SETTINGS')
# Set template variables to be injected
@app.context_processor
def inject_variables():
7 years ago
postcontent = defaultdict(str)
postcontent["title"] = initial_post["title"]
7 years ago
return {
"quote" : quote,
"postid" : initial_post["_id"],
7 years ago
"postcontent" : postcontent,
7 years ago
"links" : dumps([]),
"projects" : dumps([])
}
@login_manager.user_loader
def load_user(user_id):
return Admin
@app.route("/blog/admin_login", methods=("GET", "POST"))
def admin_login():
password = request.args.get("password")
success = False
if password == app.config["ADMIN_PASSWORD"]:
print("logged in successfully")
success = True
login_user(Admin())
else:
print("did not log in successfully")
return render_template("login.html", success=success)
# page routes
@cache.cached(timeout=50)
@app.route("/blog/posts/", methods=("GET",))
def renderInitial():
post = dict(initial_post)
return render_template("index.html",
postid=initial_post["_id"],
page="posts",
postcontent=post)
@cache.cached(timeout=50)
@app.route("/blog/projects", methods=("GET",))
def showProjects():
return render_template("index.html", page="projects")
7 years ago
@cache.cached(timeout=50)
@app.route("/blog/links", methods=("GET",))
def showLinks():
7 years ago
return render_template("index.html",
links=dumps(
list(
posts.links(json=False))),
page="links"
)
7 years ago
@cache.cached(timeout=50)
@app.route("/blog/about", methods=("GET",))
def showAbout():
return render_template("index.html", page="about")
7 years ago
@cache.cached(timeout=50)
@app.route("/blog/", methods=("GET", "POST"))
8 years ago
def index():
return renderInitial()
8 years ago
# get the next post
@cache.cached(timeout=50)
7 years ago
@app.route("/blog/posts/<_id>", methods=("GET",))
def renderPost(_id):
post_content = dict(loads(
7 years ago
cacheit(_id,
lambda: dumps(posts.getpost(_id, json=False)))
))
7 years ago
7 years ago
return render_template("index.html",
page="posts",
postcontent=post_content)
7 years ago
@cache.cached(timeout=50)
@app.route("/blog/switchpost/<pid>/<category>")
def getpostid(pid, category):
return posts.iterpost(startkey=pid, category=category)
# get the post previous to this one
@cache.cached(timeout=50)
@app.route("/blog/prevpost/<pid>/<category>")
def prevpost(pid, category):
return posts.iterpost(endkey=pid, category=category)
# get the contents of any post
@cache.cached(timeout=50)
@app.route("/blog/getpost/<_id>/<category>")
def getpost(_id, category):
return posts.getpost(_id, category=category)
# get the id of every post
@app.route("/blog/allposts")
def allposts():
return posts.allposts()
@cache.cached(timeout=10000)
@app.route("/blog/categories")
def categories():
return posts.categories()
# remove a post
@app.route("/blog/deletepost/<_id>")
@login_required
def delete(_id):
return posts.delete(_id)
# editor routes
@app.route("/blog/editor/", methods=("GET", "POST"))
@login_required
def editor():
"""
View the post editor, requires auth
"""
return render_template("write.html")
@app.route("/blog/insert/", methods=("POST",))
@login_required
def insert():
"""
Insert a post, requires auth
"""
author = request.form.get("author", "no author")
title = request.form.get("title", "no title")
content = request.form.get("content", "no content")
postid = request.form.get("_id", False)
post = {
"author" : author,
"title" : title,
"content" : content,
"_id" : postid
}
return posts.savepost(**post)
7 years ago
@app.route("/blog/glinks/", methods=("GET",))
7 years ago
def links():
"""
Get links
"""
return posts.links()
7 years ago
@app.route("/blog/ghprojects", methods=("GET",))
def projects():
return jsonify(loads(cacheit("projects", getProjects)))
8 years ago
return app
app = NeverWhere()
@app.teardown_appcontext
def teardown_couchdb(exception):
posts = getattr(g, 'posts', None)
if posts is not None:
del posts.db
posts = LocalProxy(get_posts)
7 years ago
initial_post = LocalProxy(get_initial)
login_manager.init_app(app)
csrf = CSRFProtect()
csrf.init_app(app)
cache.init_app(app)
if __name__ == "__main__":
NeverWhere().run(host="localhost", port=8001, debug=True)