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 # post the recipe in the wiki def update_wiki(recipe): import mwclient 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['Week Six: Diffractive reading methods'] text = page.text() steps = '\n'.join([f"# {log}" for log in recipe["logs"]]) # PROV TEMPLATE content = f""" === {recipe['title']} === ''{recipe['description']}''
'''Nature of the input'''
{recipe['nature']}
''' Process Log'''
{steps} '''Who'''
{recipe['who']} """ # delete multiline indentation text += '\n'.join([line.strip() for line in content.splitlines()]) page.edit(text, f'Added a new recipe! {recipe["title"]}') # 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)