7 Commits
Author SHA1 Message Date
traberph 896f13a448 manifest
Signed-off-by: Philipp Traber <traber.ph@gmail.com>
2025-05-01 16:07:55 +02:00
traberphandGitHub 076ad18f10 change emoji for consistency 2025-02-19 12:05:23 +01:00
traberphandGitHub da365ac881 Fix link in readme 2025-02-19 12:00:00 +01:00
Philipp Traber 9064802962 change base image to reduce image size
Signed-off-by: Philipp Traber <philipp.traber@uni-konstanz.de>
2024-12-05 13:02:11 +01:00
Philipp Traber 4019969841 fix versions 2024-10-08 14:33:08 +02:00
Philipp Traber 72266fe2e8 check the right ingredients 2024-10-08 13:52:55 +02:00
Philipp Traber 4f4ec345fb Bugfix - Check for spätzle on current day only rather than full week 2024-09-11 15:55:58 +02:00
8 changed files with 64 additions and 21 deletions
+3
View File
@@ -0,0 +1,3 @@
.venv
venv
__pycache__
+3 -4
View File
@@ -1,7 +1,6 @@
FROM python:3 FROM python:3.12-alpine
WORKDIR /app WORKDIR /app
COPY requirements.txt ./ COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt RUN pip install -r requirements.txt --no-cache-dir
COPY src/ . COPY src/ .
CMD [ "fastapi", "run", "api.py" ] CMD [ "fastapi", "run", "api.py" ]
+3 -3
View File
@@ -7,11 +7,11 @@ Because of the lack of eggs the spätzle are not sticking together and are just
Using the allergen information on the mensa website we can check if the spätzle are vegan or not and therefore can decide if one can eat them or not. Using the allergen information on the mensa website we can check if the spätzle are vegan or not and therefore can decide if one can eat them or not.
This project serves a simple [website](spaetzle.traberph.de) that checks the spätzle for you. This project serves a simple [website](https://spaetzle.traberph.de) that checks the spätzle for you.
## How to run ## How to run
Simply run it with docker-compose Simply run it with docker compose
``` ```
docker-compose up docker compose up
``` ```
+2 -1
View File
@@ -1,4 +1,5 @@
fastapi[standard]==0.114.0 fastapi[standard]==0.115.0
Jinja2==3.1.4 Jinja2==3.1.4
requests==2.32.3 requests==2.32.3
cachetools==5.5.0 cachetools==5.5.0
beautifulsoup4==4.12.3
+30 -7
View File
@@ -1,28 +1,44 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi import FastAPI, Request from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.responses import FileResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
import requests
from cachetools import cached, TTLCache from cachetools import cached, TTLCache
from bs4 import BeautifulSoup
import requests
import re
cache = TTLCache(maxsize=1, ttl=3600) cache = TTLCache(maxsize=1, ttl=3600)
app = FastAPI() app = FastAPI()
templates = Jinja2Templates(directory="template") templates = Jinja2Templates(directory="template")
regex = re.compile(r'Spätzle <sup>([^/]*)<\/sup>')
@cached(cache) @cached(cache)
def checkMensa(): def checkMensa():
print("Checking Mensa") print("Checking Mensa")
url = 'https://seezeit.com/essen/speiseplaene/mensa-giessberg/' url = 'https://seezeit.com/essen/speiseplaene/mensa-giessberg/'
r = requests.get(url) r = requests.get(url)
text = r.text soup = BeautifulSoup(r.text, 'html.parser')
pos = text.find('Spätzle')
if pos != -1: today = soup.find('a', class_='heute')['rel'][0]
cut = r.text[r.text.find('Spätzle'):r.text.find('Spätzle')+50] today_menu = soup.find('div', id=f'tab{today}')
ingredients = cut.split('(')[1].split(')')[0].split(',') meals = today_menu.find_all('div', class_='title')
spaetzle = None
for m in meals:
if "Spätzle" in m.text:
spaetzle = m
break
if spaetzle is not None:
ingredients = re.search(regex, str(spaetzle)).group(1)
if '28' in ingredients: if '28' in ingredients:
answer = "Spätzle with egg today" answer = "Spätzle with egg today"
color = "green" color = "green"
emoji = "✅" emoji = "✅"
else: else:
answer = "WARNING: Spätzle without egg today" answer = "WARNING: Spätzle without egg today"
color = "red" color = "red"
@@ -30,7 +46,7 @@ def checkMensa():
else: else:
answer = "No Spätzle today " answer = "No Spätzle today "
color = "grey" color = "grey"
emoji = "🤷🏻‍♂️" emoji = "🤷"
return answer, color, emoji return answer, color, emoji
@@ -41,3 +57,10 @@ async def root(request: Request):
request=request, name="main.html", context={"text": answer, "color": color , "emoji": emoji} request=request, name="main.html", context={"text": answer, "color": color , "emoji": emoji}
) )
@app.get("/manifest.json")
async def manifest(request: Request):
return FileResponse(path="assets/manifest.json")
@app.get("/icons/512.png")
async def icon(request: Request):
return FileResponse(path="assets/logo.png")
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+11
View File
@@ -0,0 +1,11 @@
{
"name": "Spätzle Check",
"icons": [
{
"src": "icons/512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
+8 -2
View File
@@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="manifest" href="/manifest.json">
<title>{{text}} - {{emoji}}</title> <title>{{text}} - {{emoji}}</title>
<style> <style>
@@ -40,7 +41,9 @@
color: #f0f0f0; color: #f0f0f0;
padding: 10px; padding: 10px;
text-align: center; text-align: center;
font-size: smaller;
} }
span { span {
background-color: salmon; background-color: salmon;
padding: 5px; padding: 5px;
@@ -48,6 +51,7 @@
border-radius: 5px; border-radius: 5px;
color: white; color: white;
} }
a { a {
text-decoration: none; text-decoration: none;
color: white; color: white;
@@ -68,8 +72,10 @@
<a href="https://kubernetes.io/de/"><span>k8s</span></a> <a href="https://kubernetes.io/de/"><span>k8s</span></a>
<a href="https://fastapi.tiangolo.com/"><span>fastapi</span></a> <a href="https://fastapi.tiangolo.com/"><span>fastapi</span></a>
<a href="https://github.com/traberph/mensa-check"><span>github</span></a> <a href="https://github.com/traberph/mensa-check"><span>github</span></a>
<a href="https://seezeit.com/essen/speiseplaene/mensa-giessberg/"><span>seezeit</span></a></p> <a href="https://seezeit.com/essen/speiseplaene/mensa-giessberg/"><span>seezeit</span></a>
<p>Imprint: <a href="https://github.com/traberph">Philipp Traber</a></p> </p>
<p>Imprint: <a href="https://github.com/traberph">Philipp Traber</a>; Legal Notice: Not associated with seezeit
</p>
</footer> </footer>
</body> </body>