get/set doors

This commit is contained in:
Jörn-Michael Miehe 2023-09-07 16:44:44 +00:00
parent 62a93d41c7
commit b3448dbfa8
7 changed files with 104 additions and 14 deletions

View file

@ -1,7 +1,10 @@
import tomli import tomllib
from typing import TypeAlias
import tomli_w
from pydantic import BaseModel from pydantic import BaseModel
from .dav_common import dav_get_textfile_content from .dav_common import dav_get_textfile_content, dav_write_textfile_content
from .settings import SETTINGS from .settings import SETTINGS
@ -16,12 +19,33 @@ class Puzzle(BaseModel):
solution: str solution: str
class Door(BaseModel):
day: int
x1: int
y1: int
x2: int
y2: int
Doors: TypeAlias = list[Door] | None
class Config(BaseModel): class Config(BaseModel):
admin: User admin: User
puzzle: Puzzle puzzle: Puzzle
doors: Doors = []
async def get_config() -> Config: async def get_config() -> Config:
txt = await dav_get_textfile_content(path=SETTINGS.config_filename) txt = await dav_get_textfile_content(path=SETTINGS.config_filename)
return Config.model_validate(tomli.loads(txt)) return Config.model_validate(tomllib.loads(txt))
async def set_config(cfg: Config) -> None:
txt = tomli_w.dumps(cfg.model_dump())
await dav_write_textfile_content(
path=SETTINGS.config_filename,
content=txt,
)

View file

@ -42,3 +42,14 @@ async def dav_get_textfile_content(path: str, encoding="utf-8") -> str:
tio = TextIOWrapper(buffer, encoding=encoding) tio = TextIOWrapper(buffer, encoding=encoding)
tio.seek(0) tio.seek(0)
return tio.read().strip() return tio.read().strip()
async def dav_write_file(path: str, buffer: BytesIO) -> None:
resource = _WEBDAV_CLIENT.resource(path)
resource.read_from(buffer)
async def dav_write_textfile_content(path: str, content: str, encoding="utf-8") -> None:
buffer = BytesIO(content.encode(encoding=encoding))
buffer.seek(0)
await dav_write_file(path, buffer)

View file

@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from PIL import Image from PIL import Image
from ..config import Config, get_config from ..config import Config, Doors, get_config, set_config
from ..dav_common import dav_get_file from ..dav_common import dav_get_file
from ._misc import api_return_image from ._misc import api_return_image
@ -23,3 +23,27 @@ async def get_image_for_day(
return await api_return_image( return await api_return_image(
Image.open(await dav_get_file(f"files/{cfg.puzzle.background}")) Image.open(await dav_get_file(f"files/{cfg.puzzle.background}"))
) )
@router.get("/doors")
async def get_doors(
cfg: Config = Depends(get_config),
) -> Doors:
"""
Türchen lesen
"""
return cfg.doors
@router.put("/doors")
async def put_doors(
doors: Doors,
cfg: Config = Depends(get_config),
) -> None:
"""
Türchen setzen
"""
cfg.doors = doors
await set_config(cfg)

12
api/poetry.lock generated
View file

@ -809,14 +809,14 @@ anyio = ">=3.4.0,<5"
full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
[[package]] [[package]]
name = "tomli" name = "tomli-w"
version = "2.0.1" version = "1.0.0"
description = "A lil' TOML parser" description = "A lil' TOML writer"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli_w-1.0.0-py3-none-any.whl", hash = "sha256:9f2a07e8be30a0729e533ec968016807069991ae2fd921a78d42f429ae5f4463"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, {file = "tomli_w-1.0.0.tar.gz", hash = "sha256:f463434305e0336248cac9c2dc8076b707d8a12d019dd349f5c1e382dd1ae1b9"},
] ]
[[package]] [[package]]
@ -1047,4 +1047,4 @@ files = [
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = "^3.11" python-versions = "^3.11"
content-hash = "eeefab88869cda6b9d33e27e438365cdaa4ff191d34e8b0229364b00678a0fd4" content-hash = "c2a27f4ecbc1c234d1368320db111d6c51cd4278986e64e80398cad384037a8c"

View file

@ -13,11 +13,11 @@ Pillow = "^10.0.0"
async-cache = "^1.1.1" async-cache = "^1.1.1"
fastapi = "^0.103.1" fastapi = "^0.103.1"
numpy = "^1.25.2" numpy = "^1.25.2"
pydantic-settings = "^2.0.3"
python = "^3.11" python = "^3.11"
tomli = "^2.0.1" tomli-w = "^1.0.0"
uvicorn = {extras = ["standard"], version = "^0.23.2"} uvicorn = {extras = ["standard"], version = "^0.23.2"}
webdavclient3 = "^3.14.6" webdavclient3 = "^3.14.6"
pydantic-settings = "^2.0.3"
[tool.poetry.group.dev.dependencies] [tool.poetry.group.dev.dependencies]
flake8 = "^6.1.0" flake8 = "^6.1.0"

View file

@ -8,6 +8,13 @@
<DoorChooser v-if="current_step === 1" v-model:doors="doors" /> <DoorChooser v-if="current_step === 1" v-model:doors="doors" />
<template v-if="current_step === 2"> <template v-if="current_step === 2">
<Calendar :doors="doors" /> <Calendar :doors="doors" />
<BulmaButton
class="is-success"
icon="fa-solid fa-crosshairs"
@click.left="load_doors"
>
Laden
</BulmaButton>
<BulmaButton <BulmaButton
class="is-success" class="is-success"
icon="fa-solid fa-crosshairs" icon="fa-solid fa-crosshairs"
@ -47,6 +54,18 @@ export default class extends Vue {
public current_step = 0; public current_step = 0;
public doors: Door[] = []; public doors: Door[] = [];
public load_doors() {
this.$advent22
.api_get_json<DoorSerialized[]>("/general/doors")
.then((data) => {
this.doors.length = 0;
for (const value of data) {
this.doors.push(Door.deserialize(value));
}
});
}
public save_doors() { public save_doors() {
const data: DoorSerialized[] = []; const data: DoorSerialized[] = [];
@ -58,8 +77,7 @@ export default class extends Vue {
data.push(door.serialized); data.push(door.serialized);
} }
console.log(data); this.$advent22.api_put("/general/doors", data);
console.log(Door.deserialize(data[0]));
} }
} }
</script> </script>

View file

@ -89,6 +89,19 @@ export class Advent22 {
public api_get_number(endpoint: string): Promise<number> { public api_get_number(endpoint: string): Promise<number> {
return this.api_get<number>(endpoint); return this.api_get<number>(endpoint);
} }
public api_get_json<T>(endpoint: string): Promise<T> {
return this.api_get<T>(endpoint);
}
public api_put(endpoint: string, data: unknown): Promise<void> {
return new Promise<void>((resolve, reject) =>
this.axios
.put(this.api_url(endpoint), data)
.then(() => resolve())
.catch(reject),
);
}
} }
export const Advent22Plugin: Plugin = { export const Advent22Plugin: Plugin = {