from flask import Flask, jsonify, request, redirect, url_for
from flask_cors import CORS, cross_origin
import datetime
import frontmatter
from glob import glob
import os
from dotenv import load_dotenv
from pathlib import Path
dotenv_path = Path("/var/www/.mw-credentials")
load_dotenv(dotenv_path=dotenv_path)
# prefix to add /SOUPBOAT/ATLAS-API to all the routes
# and to leave the @app.route() decorator more clean
class PrefixMiddleware(object):
def __init__(self, app, prefix=""):
self.app = app
self.prefix = prefix
def __call__(self, environ, start_response):
if environ["PATH_INFO"].startswith(self.prefix):
environ["PATH_INFO"] = environ["PATH_INFO"][len(self.prefix) :]
environ["SCRIPT_NAME"] = self.prefix
return self.app(environ, start_response)
else:
start_response("404", [("Content-Type", "text/plain")])
return ["This url does not belong to the app.".encode()]
base_url = "/soupboat/cookbook"
# create flask application
app = Flask(__name__)
CORS(app)
# register the middleware to prefix all the requests with our base_url
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=base_url)
# save the incoming data into a markdown file
# data is a dictionary with at least a 'title' key
def create_recipe(data):
# create filename from the title
# TODO: ensure safe filename
slug = data["title"].replace(" ", "-").lower()
today = datetime.datetime.now().strftime("%d-%m-%Y_%H-%M-%S")
# create the list of properties from the incoming data, add the date
recipe = {**data, "date": datetime.datetime.now()}
post = frontmatter.Post("", **recipe)
# save the data in a markdown file
# TODO: print directly yml file instead of md?
# since we are not really using the body of the md but just the yml frontmatter
with open(f"recipes/{slug}_{today}.md", "w") as f:
documentation = frontmatter.dumps(post)
f.write(documentation)
print(f"{data['title']} - saved in the archive")
# read the files from the recipes folder and return them in a list
def get_recipes():
recipes = []
paths = glob("recipes/*.md")
for path in paths:
with open(path, "r") as f:
meta, content = frontmatter.parse(f.read())
recipes.append(meta)
return recipes
def update_wiki(recipe):
import mwclient
import textwrap
site = mwclient.Site('pzwiki.wdka.nl', path='/mw-mediadesign/')
site.login(
username=os.environ.get('MW_BOT'),
password=os.environ.get('MW_KEY')
)
page = site.pages['Test form test form test form test']
text = page.text()
steps = ''
for log in recipe['logs']:
steps+= f'# {log}\n'
# PROV TEMPLATE
content = f"""\
=== {recipe['title']} ===
''{recipe['description']}''
'''Nature of the input'''
{recipe['nature']}
''' Process Log'''
{steps}
'''Who'''
{recipe['who']}
"""
text += textwrap.dedent(content)
page.edit(text, f'Added a new recipe! {recipe["title"]}')
# sample object to test the md output
r = {
"title": "Test test test",
"description": "A super simple description",
"logs": ["first step", "second step", "third step"],
"who": "a friend of mine",
}
# TODO: get data from client
@app.route("/", methods=["GET", "POST"])
def home():
if request.method == "POST":
create_recipe(request.json)
update_wiki(request.json)
redirect(url_for("home"))
return redirect("https://issue.xpub.nl/18/")
# return the list of recipes in JSON format
@app.route("/get")
def get():
recipes = get_recipes()
return jsonify(recipes)
# TODO: set another port and setup nginx
app.run(port=3145)