get/set doors
This commit is contained in:
		
							parent
							
								
									62a93d41c7
								
							
						
					
					
						commit
						b3448dbfa8
					
				
					 7 changed files with 104 additions and 14 deletions
				
			
		| 
						 | 
					@ -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,
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
									
									
									
								
							
							
						
						
									
										12
									
								
								api/poetry.lock
									
									
									
										generated
									
									
									
								
							| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue