You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
6.8 KiB
Python

from flask import Flask, render_template, request, redirect, url_for
from werkzeug.utils import secure_filename
import json
import sqlite3
from dotenv import load_dotenv
from pathlib import Path
import os
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()]
load_dotenv()
Path(f'static/panels/').mkdir(exist_ok=True)
Path(f'static/cables/').mkdir(exist_ok=True)
Path(f'static/snippets/').mkdir(exist_ok=True)
app = Flask(__name__)
# register the middleware to prefix all the requests with our base_url
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=os.environ.get('BASE_URL', ''))
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
def dict_from_row(row):
return dict(zip(row.keys(), row))
def create_instrument(name, description, params, sockets, panel):
slug = secure_filename(name)
panel.save(f'static/panels/{slug}.svg')
connection = get_db_connection()
cur = connection.cursor()
cur.execute(
"INSERT INTO instruments (name, slug, description, panel) VALUES (?, ?, ?, ?)",
(name, slug, description, f'{slug}.svg')
)
instrument_id = cur.lastrowid
for param in params:
cur.execute(
"INSERT OR IGNORE INTO params (param_name) VALUES (?)",(param,)
)
cur.execute(
"INSERT INTO instrument_param (instrument_id, param_name) VALUES (?, ?)", (instrument_id, param )
)
for socket in sockets:
cur.execute(
"INSERT OR IGNORE INTO sockets (socket_name) VALUES (?)", (socket,)
)
cur.execute(
"INSERT INTO instrument_socket (instrument_id, socket_name) VALUES (?, ?)", (instrument_id, socket )
)
connection.commit()
connection.close()
@app.route("/")
def workbook():
return render_template('workbook.html')
@app.route("/<slug>")
def page(slug):
return render_template(f'{slug}.html')
@app.route("/instruments")
def instruments():
connection = get_db_connection()
instruments = connection.execute('SELECT * FROM instruments').fetchall()
connection.close()
return render_template('instruments.html', instruments=instruments)
@app.route("/instruments/<instrument>")
def patches(instrument):
with open(f'static/panels/{instrument}.svg', 'r') as f:
panel = f.read()
connection = get_db_connection()
cursor = connection.cursor()
instrument = cursor.execute("SELECT * FROM instruments WHERE slug = ?", (instrument, )).fetchone()
instrument = dict_from_row(instrument)
patches = cursor.execute("SELECT * FROM patches WHERE instrument = ?", (instrument['slug'],)).fetchall()
connection.close()
return render_template('patches.html', instrument=instrument, patches=patches, panel=panel)
@app.route("/instruments/add", methods=['GET', 'POST'])
def add_instrument():
if request.method == 'POST':
name = request.form.get('name')
description = request.form.get('description')
params = json.loads(request.form.get('params'))
sockets = json.loads(request.form.get('sockets'))
panel = request.files['panel']
create_instrument(name, description, params, sockets, panel)
return redirect(url_for('instruments'))
return render_template('add_instrument.html')
@app.route("/instruments/<instrument>/add", methods=['GET', 'POST'])
def add_patch(instrument):
connection = get_db_connection()
cursor = connection.cursor()
if request.method == 'POST':
patch = request.form.to_dict()
patch = {k: v for k, v in patch.items() if v}
slug = secure_filename(patch["name"])
with open(f'static/cables/{slug}.svg', 'w') as f:
f.write(patch['cables'])
cursor.execute(
'INSERT INTO patches (name, slug, description, cables, instrument) VALUES (?,?,?,?,?)',
(patch['name'], slug, patch['description'], f"{slug}.svg", instrument)
)
patch_id = cursor.lastrowid
patch.pop('name','')
patch.pop('slug','')
patch.pop('description','')
patch.pop('cables','')
for param, value in patch.items():
cursor.execute('INSERT INTO patch_param (patch_id, param_name, value) VALUES (?,?,?)',
(patch_id, param, value))
connection.commit()
connection.close()
return redirect(url_for('patches', instrument=instrument))
with open(f'static/panels/{instrument}.svg', 'r') as f:
panel = f.read()
instrument = cursor.execute('SELECT * FROM instruments WHERE slug = ?', (instrument,)).fetchone()
connection.close()
return render_template('add_patch.html', instrument=instrument, panel = panel)
@app.route("/instruments/<instrument>/<name>", methods=['GET', 'POST'])
def patch(instrument, name):
if request.method == 'POST':
connection = get_db_connection()
cursor = connection.cursor()
file = request.files['snippet']
if file:
filename = secure_filename(file.filename)
file.save(f'static/snippets/{instrument}_{name}_{filename}')
cursor.execute('INSERT INTO snippets (filename, instrument, patch_name, description) VALUES (?,?,?,?)',
(filename, instrument, name, request.form.get('description'))
)
connection.commit()
connection.close()
redirect(url_for('patch', instrument=instrument, name=name))
connection = get_db_connection()
cursor = connection.cursor()
snippets = cursor.execute('SELECT * FROM snippets WHERE instrument = ? AND patch_name = ?',
(instrument, name)).fetchall()
patch = cursor.execute('SELECT * FROM patches WHERE instrument = ? AND slug = ?',
(instrument, name)).fetchone()
params = cursor.execute('SELECT * FROM patch_param WHERE patch_id = ?',
(patch['id'],)).fetchall()
instrument = cursor.execute('SELECT * FROM instruments WHERE slug = ?',
(instrument,)).fetchone()
with open(f'static/panels/{instrument["slug"]}.svg') as f:
panel = f.read()
connection.close()
return render_template('patch.html', instrument=instrument, patch=patch, params=params, panel=panel, snippets=snippets)
app.run(port=os.environ.get('FLASK_RUN_PORT'), debug=True)