Restructure project

This commit is contained in:
Fabian Müller 2022-11-21 02:53:55 +01:00
parent 8209049486
commit 4af54f3287
8 changed files with 125 additions and 100 deletions

View File

@ -18,4 +18,4 @@ COPY main.py /app/
COPY static/ /app/static/
COPY templates/ /app/templates/
ENTRYPOINT ["poetry", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "5000", "--use-colors"]
ENTRYPOINT ["poetry", "run", "uvicorn", "fabcal.app:app", "--host", "0.0.0.0", "--port", "5000", "--use-colors"]

0
fabcal/__init__.py Normal file
View File

33
fabcal/app.py Normal file
View File

@ -0,0 +1,33 @@
import locale
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi_cache import FastAPICache
from fastapi_cache.backends.inmemory import InMemoryBackend
from fabcal.routers import api_v1, frontend
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
app.include_router(api_v1.router, prefix="/api/v1")
app.include_router(frontend.router, prefix="")
app.add_middleware(
CORSMiddleware,
allow_origins=[
"https://fablab-altmuehlfranken.de",
"https://www.fablab-altmuehlfranken.de",
],
)
locale.setlocale(locale.LC_TIME, locale.getlocale())
@app.on_event("startup")
async def startup():
FastAPICache.init(InMemoryBackend())

View File

@ -1,53 +1,16 @@
import base64
import locale
import os
from collections import OrderedDict
from datetime import date, datetime, timedelta, timezone
from typing import List, NamedTuple
from typing import List
import aiohttp
import babel.dates
import recurring_ical_events
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.requests import Request
from fastapi.responses import Response
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi_cache import FastAPICache
from fastapi_cache.backends.inmemory import InMemoryBackend
from fastapi_cache.decorator import cache
from icalendar import Calendar, vText
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
app.add_middleware(
CORSMiddleware,
allow_origins=[
"https://fablab-altmuehlfranken.de",
"https://www.fablab-altmuehlfranken.de",
],
)
locale.setlocale(locale.LC_TIME, locale.getlocale())
def get_calendar_url():
url = os.environ["CALENDAR_URL"]
# convenience feature
url = url.replace("webcal://", "https://")
return url
from fabcal.models import CalendarEvent
def sanitize(data: str):
@ -60,6 +23,15 @@ def sanitize(data: str):
return cal.to_ical()
def get_calendar_url():
url = os.environ["CALENDAR_URL"]
# convenience feature
url = url.replace("webcal://", "https://")
return url
# caching strings works better than caching calendar objects
@cache(expire=120)
async def get_data() -> str:
@ -71,18 +43,6 @@ async def get_data() -> str:
return sanitize(await response.text())
class CalendarEvent(NamedTuple):
start: datetime
end: datetime
# just a convenience thing, we want to keep start/date as datetime and save the client from guessing this themselves
all_day_event: bool
summary: str
description: str
location: str
color: str
uid: str
def get_tzinfo():
return timezone(timedelta(hours=1))
@ -163,16 +123,6 @@ async def get_future_events():
return future_events
@app.get("/events.ics")
async def ics():
return Response(
await get_data(),
headers={
"content-type": "text/calendar",
},
)
def group_by_date(events: List[CalendarEvent]):
grouped_events: OrderedDict[date, List[CalendarEvent]] = OrderedDict()
@ -185,41 +135,3 @@ def group_by_date(events: List[CalendarEvent]):
grouped_events[start_date].append(event)
return grouped_events
@app.get("/embed-sidebar.html")
async def embed(request: Request, max_width: str = None):
# await asyncio.sleep(1)
events = await get_future_events()
grouped_events = list(group_by_date(events).items())
# couple of helpers
def localized_abbreviated_month(dt: datetime):
return babel.dates.format_datetime(dt, format="%b", locale="de_DE")
# couple of helpers
def localized_abbreviated_weekday(dt: datetime):
return babel.dates.format_datetime(dt, format="%b", locale="de_DE")
def base64_encode(s: str):
return base64.b64encode(s.encode()).decode()
return templates.TemplateResponse(
"embed-sidebar.html",
context={
"request": request,
"grouped_events": grouped_events,
"dir": dir,
"localized_abbreviated_month": localized_abbreviated_month,
"localized_abbreviated_weekday": localized_abbreviated_weekday,
"base64_encode": base64_encode,
"max_width": max_width,
},
)
@app.on_event("startup")
async def startup():
FastAPICache.init(InMemoryBackend())

14
fabcal/models.py Normal file
View File

@ -0,0 +1,14 @@
from datetime import datetime
from typing import NamedTuple
class CalendarEvent(NamedTuple):
start: datetime
end: datetime
# just a convenience thing, we want to keep start/date as datetime and save the client from guessing this themselves
all_day_event: bool
summary: str
description: str
location: str
color: str
uid: str

View File

@ -0,0 +1,4 @@
from starlette.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates")

17
fabcal/routers/api_v1.py Normal file
View File

@ -0,0 +1,17 @@
from fastapi import APIRouter
from starlette.responses import Response
from fabcal.calendar_client import get_data
router = APIRouter()
@router.get("/events.ics")
async def events():
return Response(
await get_data(),
headers={
"content-type": "text/calendar",
},
)

View File

@ -0,0 +1,45 @@
import base64
from datetime import datetime
import babel.dates
from fastapi import APIRouter
from fastapi.requests import Request
from fastapi.responses import HTMLResponse
from fabcal.calendar_client import get_future_events, group_by_date
from fabcal.routers import templates
router = APIRouter()
@router.get("/embed-sidebar.html", response_class=HTMLResponse)
async def embed(request: Request, max_width: str = None):
events = await get_future_events()
grouped_events = list(group_by_date(events).items())
# couple of helpers
def localized_abbreviated_month(dt: datetime):
return babel.dates.format_datetime(dt, format="%b", locale="de_DE")
# couple of helpers
def localized_abbreviated_weekday(dt: datetime):
return babel.dates.format_datetime(dt, format="%b", locale="de_DE")
def base64_encode(s: str):
return base64.b64encode(s.encode()).decode()
return templates.TemplateResponse(
"embed-sidebar.html",
context={
"request": request,
"grouped_events": grouped_events,
"dir": dir,
"localized_abbreviated_month": localized_abbreviated_month,
"localized_abbreviated_weekday": localized_abbreviated_weekday,
"base64_encode": base64_encode,
},
)