Compare commits
30 Commits
614c16750d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 5fa1ecf46e | |||
|
|
3dab312a74 | ||
|
|
364c6391c9 | ||
|
|
439e637a86 | ||
|
|
d9808cc66e | ||
|
|
f139fa4bc4 | ||
|
|
1af0e1f834 | ||
|
|
b0a88b1916 | ||
|
|
cf95503954 | ||
|
|
6cdf83b6d0 | ||
|
|
21a747e097 | ||
|
|
05faf28c26 | ||
|
|
154ab9089d | ||
|
|
429e2d221e | ||
|
|
f3d697699d | ||
|
|
02645b7ef7 | ||
|
|
9112763234 | ||
|
|
7a2fdec8d4 | ||
|
|
674edf2bf2 | ||
|
|
e76d9815c9 | ||
|
|
204269b849 | ||
|
|
c969dc0e2d | ||
|
|
b183059f85 | ||
|
|
b1e05e8e4d | ||
|
|
10bea4b46b | ||
|
|
0ede5055e2 | ||
|
|
d17c6f6142 | ||
|
|
fe7b0a9e41 | ||
|
|
3b659ab076 | ||
|
|
1819826151 |
@@ -23,7 +23,8 @@ app:
|
|||||||
name: THSF
|
name: THSF
|
||||||
real_url: https://www.thsf.net
|
real_url: https://www.thsf.net
|
||||||
pretalx:
|
pretalx:
|
||||||
url: https://23.thsf.net
|
url: https://thsf.tetaneutral.net
|
||||||
|
ssl_verify: False
|
||||||
apiprefix: api
|
apiprefix: api
|
||||||
apikey: bb770a53b15467dfb67c03d178004aca9e4819d6
|
apikey: bb770a53b15467dfb67c03d178004aca9e4819d6
|
||||||
event: thsf-2023
|
event: thsf-2023
|
||||||
|
|||||||
4
maintenance/reboot.py
Normal file → Executable file
4
maintenance/reboot.py
Normal file → Executable file
@@ -4,10 +4,10 @@ import docker
|
|||||||
client = docker.from_env()
|
client = docker.from_env()
|
||||||
for container in client.containers.list():
|
for container in client.containers.list():
|
||||||
if container.name == "thsf":
|
if container.name == "thsf":
|
||||||
|
print("Content-type: text/html\n\n")
|
||||||
print("[+] Rebooting container<br>")
|
print("[+] Rebooting container<br>")
|
||||||
print(" '-> Stopping container<br>")
|
print(" '-> Stopping container<br>")
|
||||||
container.stop()
|
container.stop()
|
||||||
print(" '-> Starting container<br>")
|
print(" '-> Starting container<br>")
|
||||||
container.start()
|
container.start()
|
||||||
print("[\o/] Container restarted<br>")
|
print("[+] Container restarted<br>")
|
||||||
|
|
||||||
|
|||||||
2
maintenance/scripts/jquery-3.7.0.min.js
vendored
Normal file
2
maintenance/scripts/jquery-3.7.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,13 +1,7 @@
|
|||||||
function reboot() {
|
$("#reboot").on("click", function(){
|
||||||
var xhttp = new XMLHttpRequest();
|
$.get("https://www.thsf.net/thsf.net/maintenance/reboot.py", function(data, status){
|
||||||
xhttp.onreadystatechange = function() {
|
console.log(status);
|
||||||
if (this.readyState == 4 && this.status == 200) {
|
$("#logs").html = data;
|
||||||
document.getElementById("logs").innerHTML = this.responseText;
|
setTimeout(function () {document.location.reload()}, 5000);
|
||||||
}
|
});
|
||||||
};
|
});
|
||||||
xhttp.open("GET", "https://www.thsf.net/maintenance/reboot.py", true);
|
|
||||||
xhttp.send();
|
|
||||||
setTimeout(function () {
|
|
||||||
document.location="https://www.thsf.net/maintenance/status.py"}, 5000
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
4
maintenance/status.py
Normal file → Executable file
4
maintenance/status.py
Normal file → Executable file
@@ -15,5 +15,5 @@ for container in client.containers.list():
|
|||||||
cont = dict()
|
cont = dict()
|
||||||
cont["name"] = container.name
|
cont["name"] = container.name
|
||||||
cont["status"] = container.status
|
cont["status"] = container.status
|
||||||
cont["log"] = container.logs().decode('utf-8').replace('\n', '<br>')
|
cont["logs"] = container.logs().decode('utf-8').replace('\n', '<br>')
|
||||||
print(template.render(containers=[container]))
|
print(template.render(containers=[cont]))
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
.body {
|
body {
|
||||||
|
font-size: 1.2em;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
.page_wrapper {
|
.page_wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -8,8 +9,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-bottom: 5em;
|
|
||||||
background-color: red;
|
|
||||||
}
|
}
|
||||||
.center_wrapper {
|
.center_wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -17,7 +16,6 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: blue;
|
|
||||||
}
|
}
|
||||||
.container_list {
|
.container_list {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -25,20 +23,25 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: yellow;
|
width: 48em;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0.5em;
|
||||||
}
|
}
|
||||||
.table_headers, .line {
|
.table_headers, .line {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: green;
|
|
||||||
}
|
}
|
||||||
.header, .status {
|
.header, .status {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
background-color: violet;
|
width: 16em;
|
||||||
|
padding: 0.2em;
|
||||||
}
|
}
|
||||||
.table_content {
|
.table_content {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -46,14 +49,18 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: cyan;
|
|
||||||
}
|
}
|
||||||
.status {
|
.status {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
.container_log {
|
.container_log {
|
||||||
|
text-align: left;
|
||||||
|
width: 49em;
|
||||||
|
padding: 0.2em;
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
}
|
}
|
||||||
.button {
|
.button {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,24 @@
|
|||||||
|
Content-type: text/html
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang='zxx'>
|
<html lang='zxx'>
|
||||||
<head>
|
<head>
|
||||||
<title>THSF 2023: Status page</title>
|
<title>THSF 2023: Status page</title>
|
||||||
<meta name="viewport" content="initial-scale=1.0">
|
<meta name="viewport" content="initial-scale=1.0">
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
<script src="/maintenance/scripts/maintenance.js"></script>
|
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="/maintenance/style/maintenance.css">
|
href="/thsf.net/maintenance/style/maintenance.css">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
|
<script src="/thsf.net/maintenance/scripts/jquery-3.7.0.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="page_wrapper">
|
<div class="page_wrapper">
|
||||||
<div class="center_wrapper">
|
<div class="center_wrapper">
|
||||||
<div class="container_list">
|
<div class="container_list">
|
||||||
|
<div class="line">
|
||||||
|
<span class="title">THSF Status</span>
|
||||||
|
</div>
|
||||||
<div class="table_headers">
|
<div class="table_headers">
|
||||||
<div class="header">Name</div>
|
<div class="header">Name</div>
|
||||||
<div class="header">Status</div>
|
<div class="header">Status</div>
|
||||||
@@ -25,16 +30,17 @@
|
|||||||
<div class="status">{{ container.name }}</div>
|
<div class="status">{{ container.name }}</div>
|
||||||
<div class="status">{{ container.status }}</div>
|
<div class="status">{{ container.status }}</div>
|
||||||
<div class="status">
|
<div class="status">
|
||||||
<i class="button fa-regular fa-recycle" onclick=""></i>
|
<i id="reboot" class="button fa-solid fa-recycle" title="Reboot container" alt="Reboot container"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container_log" id="logs">
|
<div class="container_log" id="logs">
|
||||||
{{ container.logs }}
|
{{ container.logs | safe }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="/thsf.net/maintenance/scripts/maintenance.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
from logging import config
|
from logging import config
|
||||||
import yaml
|
import yaml
|
||||||
from flask import Flask, render_template, redirect, request, url_for
|
from flask import Flask, render_template, redirect, url_for
|
||||||
from flask_minify import minify
|
from flask_minify import minify
|
||||||
from thsf.backend import Backend
|
from thsf.backend import Backend
|
||||||
from thsf.schedule import Schedule
|
from thsf.schedule import Schedule
|
||||||
@@ -37,7 +35,8 @@ try:
|
|||||||
config.dictConfig(app.local_config["log"])
|
config.dictConfig(app.local_config["log"])
|
||||||
backend = Backend(url=app.local_config["pretalx"]["url"],
|
backend = Backend(url=app.local_config["pretalx"]["url"],
|
||||||
apiprefix=app.local_config["pretalx"]["apiprefix"],
|
apiprefix=app.local_config["pretalx"]["apiprefix"],
|
||||||
apikey=app.local_config["pretalx"]["apikey"])
|
apikey=app.local_config["pretalx"]["apikey"],
|
||||||
|
ssl_verify=app.local_config["pretalx"]["ssl_verify"])
|
||||||
schedule = Schedule()
|
schedule = Schedule()
|
||||||
navbar = Navbar(config=app.local_config["navbar"])
|
navbar = Navbar(config=app.local_config["navbar"])
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
@@ -47,6 +46,7 @@ except Exception as err:
|
|||||||
if app.local_config["log"]["root"]["level"] != "DEBUG":
|
if app.local_config["log"]["root"]["level"] != "DEBUG":
|
||||||
minify(app=app, html=True, js=True, cssless=True)
|
minify(app=app, html=True, js=True, cssless=True)
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# -- Tools
|
# -- Tools
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -63,7 +63,7 @@ def get_speaker_biography(code):
|
|||||||
try:
|
try:
|
||||||
speaker_info = backend.get(endpoint=f"events/{app.local_config['pretalx']['event']}/speakers/{code}/").json()
|
speaker_info = backend.get(endpoint=f"events/{app.local_config['pretalx']['event']}/speakers/{code}/").json()
|
||||||
return speaker_info.get("biography").strip()
|
return speaker_info.get("biography").strip()
|
||||||
except Exception as err:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -125,9 +125,10 @@ def planning():
|
|||||||
for slot in slots.get("slots"):
|
for slot in slots.get("slots"):
|
||||||
for speaker in slot.get("speakers"):
|
for speaker in slot.get("speakers"):
|
||||||
speaker["biography"] = get_speaker_biography(speaker.get("code"))
|
speaker["biography"] = get_speaker_biography(speaker.get("code"))
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/planning"),
|
navbar=navbar.get_from_page(page="/planning"),
|
||||||
filter=["concert", "dj set", "panel discussion", "talk", "screening"])
|
filter=["concert", "dj set", "panel discussion", "talk", "screening"])
|
||||||
|
|
||||||
@@ -153,9 +154,10 @@ def goodies():
|
|||||||
@app.route('/concerts', methods=['GET'])
|
@app.route('/concerts', methods=['GET'])
|
||||||
def concerts():
|
def concerts():
|
||||||
slots = get_slots()
|
slots = get_slots()
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/concerts"),
|
navbar=navbar.get_from_page(page="/concerts"),
|
||||||
filter=["concert", "dj set"])
|
filter=["concert", "dj set"])
|
||||||
|
|
||||||
@@ -163,9 +165,10 @@ def concerts():
|
|||||||
@app.route('/workshops', methods=['GET'])
|
@app.route('/workshops', methods=['GET'])
|
||||||
def workshops():
|
def workshops():
|
||||||
slots = get_slots()
|
slots = get_slots()
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/workshops"),
|
navbar=navbar.get_from_page(page="/workshops"),
|
||||||
filter=["workshop"])
|
filter=["workshop"])
|
||||||
|
|
||||||
@@ -173,9 +176,10 @@ def workshops():
|
|||||||
@app.route('/screenings', methods=['GET'])
|
@app.route('/screenings', methods=['GET'])
|
||||||
def screenings():
|
def screenings():
|
||||||
slots = get_slots()
|
slots = get_slots()
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/screenings"),
|
navbar=navbar.get_from_page(page="/screenings"),
|
||||||
filter=["screening"])
|
filter=["screening"])
|
||||||
|
|
||||||
@@ -183,9 +187,10 @@ def screenings():
|
|||||||
@app.route('/discussions', methods=['GET'])
|
@app.route('/discussions', methods=['GET'])
|
||||||
def discussions():
|
def discussions():
|
||||||
slots = get_slots()
|
slots = get_slots()
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/discussions"),
|
navbar=navbar.get_from_page(page="/discussions"),
|
||||||
filter=["panel discussion"])
|
filter=["panel discussion"])
|
||||||
|
|
||||||
@@ -193,9 +198,10 @@ def discussions():
|
|||||||
@app.route('/exhibitions', methods=['GET'])
|
@app.route('/exhibitions', methods=['GET'])
|
||||||
def exhibitions():
|
def exhibitions():
|
||||||
slots = get_slots()
|
slots = get_slots()
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/exhibitions"),
|
navbar=navbar.get_from_page(page="/exhibitions"),
|
||||||
filter=["installation"])
|
filter=["installation"])
|
||||||
|
|
||||||
@@ -203,9 +209,10 @@ def exhibitions():
|
|||||||
@app.route('/talks', methods=['GET'])
|
@app.route('/talks', methods=['GET'])
|
||||||
def talks():
|
def talks():
|
||||||
slots = get_slots()
|
slots = get_slots()
|
||||||
return render_template("planning.html",
|
|
||||||
slots = sorted(slots.get("slots"),
|
slots = sorted(slots.get("slots"),
|
||||||
key=lambda slot: slot.get("slot").get("start")),
|
key=lambda slot: slot.get("slot").get("start"))
|
||||||
|
return render_template("planning.html",
|
||||||
|
slots=slots,
|
||||||
navbar=navbar.get_from_page(page="/talks"),
|
navbar=navbar.get_from_page(page="/talks"),
|
||||||
filter=["talk", "light talk"])
|
filter=["talk", "light talk"])
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import requests
|
import requests
|
||||||
import logging
|
|
||||||
|
|
||||||
class Backend:
|
class Backend:
|
||||||
def __init__(self, url, apiprefix, apikey):
|
def __init__(self, url, apiprefix, apikey, ssl_verify):
|
||||||
self.url = url
|
self.url = url
|
||||||
self.apiprefix = apiprefix
|
self.apiprefix = apiprefix
|
||||||
self.apikey = apikey
|
self.apikey = apikey
|
||||||
|
self.ssl_verify = ssl_verify
|
||||||
self.session = requests.Session()
|
self.session = requests.Session()
|
||||||
|
|
||||||
def get(self, endpoint, params=None):
|
def get(self, endpoint, params=None):
|
||||||
url = f"{self.url}/{self.apiprefix}/{endpoint}"
|
url = f"{self.url}/{self.apiprefix}/{endpoint}"
|
||||||
headers = {"Authorization": f"Token {self.apikey}",
|
headers = {"Authorization": f"Token {self.apikey}",
|
||||||
"Accept": "application/json"}
|
"Accept": "application/json"}
|
||||||
return self.session.get(url, params=params, headers=headers)
|
return self.session.get(url,
|
||||||
|
params=params,
|
||||||
|
headers=headers,
|
||||||
|
verify=self.ssl_verify)
|
||||||
|
|||||||
@@ -23,5 +23,7 @@
|
|||||||
<p>Comme toujours, notre objectif est de créer un festival qui poétise les bifurcations de nos idées communes et qui réinvente le sens de certains schémas imposés par notre époque. Rejoignez-nous pour une expérience enrichissante et pleine de surprises !</p>
|
<p>Comme toujours, notre objectif est de créer un festival qui poétise les bifurcations de nos idées communes et qui réinvente le sens de certains schémas imposés par notre époque. Rejoignez-nous pour une expérience enrichissante et pleine de surprises !</p>
|
||||||
|
|
||||||
<p>Retrouvez <a href="/planning">le programme du THSF</a> avec ses <a href="/workshops">ateliers</a>, ses <a href="/exhibitions">expositions et installations</a> mais également ses <a href="/concerts">concerts</a>, ses <a href="/projections">projections</a>, ses <a href="/talks">présentations</a> et ses <a href="/discussions">tables rondes</a>.</p>
|
<p>Retrouvez <a href="/planning">le programme du THSF</a> avec ses <a href="/workshops">ateliers</a>, ses <a href="/exhibitions">expositions et installations</a> mais également ses <a href="/concerts">concerts</a>, ses <a href="/projections">projections</a>, ses <a href="/talks">présentations</a> et ses <a href="/discussions">tables rondes</a>.</p>
|
||||||
|
<p>Accéder aux conférences, tables rondes et reportages grâce à nos amis de TVBruits: <a href="https://tvbruits.org/spip.php?mot87">https://tvbruits.org/spip.php?mot87</a>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
<p>Accéder aux conférences, tables rondes et reportages grâce à nos amis de TVBruits: <a href="https://tvbruits.org/spip.php?mot87">https://tvbruits.org/spip.php?mot87</a>
|
||||||
|
</p>
|
||||||
{% for slot in slots %}
|
{% for slot in slots %}
|
||||||
{% set loop_index = loop.index %}
|
{% set loop_index = loop.index %}
|
||||||
{% if filter %}
|
{% if filter %}
|
||||||
|
|||||||
Reference in New Issue
Block a user