init and backend setup

master
km0 3 years ago
commit bc8dac4e11

2
.gitignore vendored

@ -0,0 +1,2 @@
.env
venv/

@ -0,0 +1,132 @@
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
# Flask application to serve the web pages
from flask import Flask, render_template, request, redirect, url_for
# Mediawiki client to interact with the Wiki
import mwclient
# BS to read the html table from the wiki
from bs4 import BeautifulSoup
# os and dotenv to store the mediawiki credentials in a safe place
import os
from dotenv import load_dotenv
from pathlib import Path
# load the mediawiki credentials from the shared folder
dotenv_path = Path("/var/www/.mw-credentials")
load_dotenv(dotenv_path=dotenv_path)
# prefix to add /soupboat/padliography 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()]
# create flask application
app = Flask(__name__)
# Url prefix for the soupboat
base_url = "/soupboat/padliography"
# Page of the wiki with the pads
padliography = 'Padliography2'
# register the middleware to prefix all the requests with our base_url
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=base_url)
def add_pad(link, title, overview, categories, date):
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[padliography]
text = page.text()
new_row = f'|-\n| {link} || {title} || {overview} || {categories} || {date}\n|-\n' + '|}'
text = text.replace('|}', new_row)
page.edit(text, f'New pad in the {padliography}: {title}')
def get_pads():
site = mwclient.Site('pzwiki.wdka.nl', path='/mw-mediadesign/')
site.login(
username=os.environ.get('MW_BOT'),
password=os.environ.get('MW_KEY')
)
html = site.api('parse', prop='text', page=padliography)
pads = BeautifulSoup(html['parse']['text']['*']).find("table", attrs={"class":"padliography"})
return pads
@app.route('/')
def home():
pads = get_pads()
return render_template('index.html', pads=pads)
@app.route('/add')
def add():
link = request.args.get('link', None)
title = request.args.get('title', None)
overview = request.args.get('overview', '')
categories = request.args.get('categories', '')
date = request.args.get('date', None)
if None not in (link, title, date):
add_pad(link, title, overview, categories, date)
redirect(url_for('home'))
return render_template('index.html')
app.run(port=3146)

@ -0,0 +1,22 @@
beautifulsoup4==4.11.1
certifi==2022.5.18.1
charset-normalizer==2.0.12
click==8.1.3
colorama==0.4.4
Flask==2.1.2
idna==3.3
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.1
mwclient==0.10.1
numpy==1.22.4
oauthlib==3.2.0
python-dateutil==2.8.2
python-dotenv==0.20.0
pytz==2022.1
requests==2.27.1
requests-oauthlib==1.3.1
six==1.16.0
soupsieve==2.3.2.post1
urllib3==1.26.9
Werkzeug==2.1.2

@ -0,0 +1,124 @@
body {
font-size: 1.5rem;
margin: 0;
background: rgb(255, 244, 235);
}
.contents {
margin: 32px;
}
h1 {
color: #ecab72;
margin: 32px;
text-align: center;
}
a {
color: currentColor;
}
a.stretched-link::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
}
/* FILTERS */
.tag {
background: none;
font-size: 20px;
display: inline-block;
border: 1px solid currentColor;
padding: 0 0.5em;
border-radius: 1em;
margin: 4px;
text-transform: capitalize;
user-select: none;
cursor: pointer;
transform: translateY(0);
transition: transform 0.4s ease-in;
}
.tag.active {
background-color: white;
}
.tag.active.all {
background: none;
}
.filters .tag:focus,
.filters .tag:hover {
transform: translateY(-4px);
transition: transform 0.2s ease-out;
}
ul {
padding: 0;
}
/* TABLE */
table {
border-collapse: collapse;
}
tr {
/* display: none; */
position: relative;
}
tr:nth-child(even) {
background-color: rgb(251, 237, 225);
}
tr.active {
display: table-row;
}
tr:hover {
background-color: rgb(250, 232, 217);
}
tr .tag {
cursor: default;
}
tr.header {
display: table-row;
text-align: left;
}
.categories {
width: 20%;
}
.overview {
font-style: italic;
width: 40%;
}
.date {
width: 14ch;
}
form {
margin: 32px;
display: inline-block;
padding: 2rem;
background-color: rgb(250, 232, 217);
border-radius: 50%;
}
form h2 {
margin: 0;
margin-bottom: 16px;
font-size: 28px;
}

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="{{url_for('static', filename='css/style.css')}}" />
<title>Padliography II</title>
</head>
<body>
<form action="add">
<h2>Add a new pad</h2>
<label for="link">link</label>
<input type="text" name="link" />
<label for="title">title</label>
<input type="text" name="title" />
<label for="overview">overview</label>
<input type="text" name="overview" />
<label for="categories">categories</label>
<input type="text" name="categories" />
<label for="date">date</label>
<input type="date" name="date" />
<input type="submit" value="Add" />
</form>
{% if pads %} {{pads|safe}} {%endif%}
</body>
</html>
Loading…
Cancel
Save