Compare commits

...

2 Commits

Author SHA1 Message Date
km0 ecd42c85ad coding documentation 2 years ago
km0 e8ab523cf8 source code commentary 2 years ago

@ -7,7 +7,6 @@ import mwclient
# BS to read the html table from the wiki # BS to read the html table from the wiki
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
# os and dotenv to store the mediawiki credentials in a safe place # os and dotenv to store the mediawiki credentials in a safe place
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
@ -21,8 +20,6 @@ load_dotenv(dotenv_path=dotenv_path)
load_dotenv() load_dotenv()
# prefix to add /soupboat/padliography to all the routes # prefix to add /soupboat/padliography to all the routes
# and to leave the @app.route() decorator more clean
class PrefixMiddleware(object): class PrefixMiddleware(object):
def __init__(self, app, prefix=""): def __init__(self, app, prefix=""):
self.app = app self.app = app
@ -42,69 +39,87 @@ class PrefixMiddleware(object):
# create flask application # create flask application
app = Flask(__name__) app = Flask(__name__)
# Get the URL prefix for the soupboat
# Url prefix for the soupboat and port # register the middleware to use our base_url as prefix on all the requests
base_url = os.environ.get('BASE_URL', '') base_url = os.environ.get('BASE_URL', '')
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=base_url)
port = os.environ.get('FLASK_RUN_PORT', '')
# Page of the wiki with the pads # Page of the wiki with the pads
padliography = os.environ.get('PAGE', '') padliography = os.environ.get('PAGE', '')
# 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): def add_pad(link, title, overview, categories, date):
'''Add a new pad to the wiki page'''
# 1. Connect to the wiki
site = mwclient.Site('pzwiki.wdka.nl', path='/mw-mediadesign/') site = mwclient.Site('pzwiki.wdka.nl', path='/mw-mediadesign/')
# 2. Authenticate using the credential of a bot user registered in the wiki
### This is necesary the edit the contents of the page
site.login( site.login(
username=os.environ.get('MW_BOT'), username=os.environ.get('MW_BOT'),
password=os.environ.get('MW_KEY') password=os.environ.get('MW_KEY')
) )
# 3. Select the page and get the contents
page = site.pages[padliography] page = site.pages[padliography]
text = page.text() text = page.text()
# 4. Append the pad as new row in the table of pads
new_row = f'|-\n| {link} || {title} || {overview} || {categories} || {date} \n|-\n' + '|}' new_row = f'|-\n| {link} || {title} || {overview} || {categories} || {date} \n|-\n' + '|}'
text = text.replace('|}', new_row) text = text.replace('|}', new_row)
# 5. Apply the edit
page.edit(text, f'New pad in the {padliography}: {title}') page.edit(text, f'New pad in the {padliography}: {title}')
def get_pads(): def get_pads():
'''Retrieve pads from the wiki'''
# 1. Connect to the wiki
site = mwclient.Site('pzwiki.wdka.nl', path='/mw-mediadesign/') site = mwclient.Site('pzwiki.wdka.nl', path='/mw-mediadesign/')
# 2. Log in using the credential of a bot user registered in the wiki
site.login( site.login(
username=os.environ.get('MW_BOT'), username=os.environ.get('MW_BOT'),
password=os.environ.get('MW_KEY'), password=os.environ.get('MW_KEY'),
) )
# 3. Use the MediaWiki API to get the wikitext contents in HTML
html = site.api('parse', prop='text', page=padliography) html = site.api('parse', prop='text', page=padliography)
# 4. Parse the HTML with BeautifulSoup to extract data from the table of pads
table = BeautifulSoup(html['parse']['text']['*'], features="html.parser").find( table = BeautifulSoup(html['parse']['text']['*'], features="html.parser").find(
"table", attrs={"class": "padliography"}) "table", attrs={"class": "padliography"})
# 5. Find the headers of the table
headers = [header.text.lower().strip() for header in table.find_all('th')] headers = [header.text.lower().strip() for header in table.find_all('th')]
# 6. Create a list of pad, using each header as property of the object pad
pads = [ pads = [
{headers[i]: cell.text.rstrip('\n') {headers[i]: cell.text.rstrip('\n')
for i, cell in enumerate(row.find_all('td'))} for i, cell in enumerate(row.find_all('td'))}
for row in table.find_all('tr')] for row in table.find_all('tr')]
#7. Remove empty pads from the list
pads = [pad for pad in pads if pad != {}] pads = [pad for pad in pads if pad != {}]
return pads
return pads
# Routes
@app.route('/') @app.route('/')
def home(): def home():
'''Serve the homepage layout'''
return render_template('home.html') return render_template('home.html')
@app.route('/api', methods=['GET', 'POST']) @app.route('/api', methods=['GET', 'POST'])
def api(): def api():
'''Manage the interaction with the MediaWiki API'''
# Add a new pad
if request.method == 'POST': if request.method == 'POST':
link = request.json.get('link', None) link = request.json.get('link', None)
title = request.json.get('title', None) title = request.json.get('title', None)
@ -112,11 +127,10 @@ def api():
categories = request.json.get('categories', '') categories = request.json.get('categories', '')
date = request.json.get('date', None) date = request.json.get('date', None)
# date = datetime.strftime(datetime.strptime(
# date, '%Y-%m-%d'), '%d-%m-%Y')
add_pad(link, title, overview, categories, date) add_pad(link, title, overview, categories, date)
redirect(url_for('home')) redirect(url_for('home'))
# Return the pad list
response = jsonify({ response = jsonify({
'page': padliography, 'page': padliography,
'pads': get_pads() 'pads': get_pads()
@ -126,4 +140,7 @@ def api():
return response return response
# Get the port and mount the app
port = os.environ.get('FLASK_RUN_PORT', '')
app.run(port=port) app.run(port=port)

@ -36,7 +36,7 @@ export default {
}; };
PadStore.value.unshift(pad); PadStore.value.unshift(pad);
pad.categories.join(", "); pad.categories = pad.categories.join(", ");
fetch("api", { fetch("api", {
method: "POST", method: "POST",
@ -79,7 +79,6 @@ export default {
<input class='date' type="date" v-model="date" placeholder="Date" /> <input class='date' type="date" v-model="date" placeholder="Date" />
<button @click="submit" class="submit">Insert</button> <button @click="submit" class="submit">Insert</button>
</div> </div>

Loading…
Cancel
Save