초기 커밋

This commit is contained in:
2026-03-01 07:44:19 +09:00
commit 09359f30be
146 changed files with 6120 additions and 0 deletions

0
app/utils/__init__.py Normal file
View File

View File

@@ -0,0 +1,17 @@
from __future__ import annotations
from datetime import datetime, timezone, timedelta
KST = timezone(timedelta(hours=9))
def now_utc() -> datetime:
return datetime.now(timezone.utc)
def now_kst() -> datetime:
return datetime.now(KST)
def utc_to_kst(dt: datetime) -> datetime:
return dt.astimezone(KST)

23
app/utils/file_utils.py Normal file
View File

@@ -0,0 +1,23 @@
from __future__ import annotations
import os
import uuid
from fastapi import UploadFile
UPLOAD_DIR = "uploads"
async def save_upload(file: UploadFile, subdir: str = "") -> str:
directory = os.path.join(UPLOAD_DIR, subdir) if subdir else UPLOAD_DIR
os.makedirs(directory, exist_ok=True)
ext = os.path.splitext(file.filename or "")[1]
filename = f"{uuid.uuid4().hex}{ext}"
filepath = os.path.join(directory, filename)
content = await file.read()
with open(filepath, "wb") as f:
f.write(content)
return filepath

12
app/utils/pagination.py Normal file
View File

@@ -0,0 +1,12 @@
from __future__ import annotations
from typing import TypeVar
from app.schemas.common import PaginatedResponse
T = TypeVar("T")
def paginate(items: list[T], total: int, page: int, size: int) -> PaginatedResponse[T]:
pages = (total + size - 1) // size if size > 0 else 0
return PaginatedResponse(items=items, total=total, page=page, size=size, pages=pages)

11
app/utils/validators.py Normal file
View File

@@ -0,0 +1,11 @@
from __future__ import annotations
import re
def is_valid_device_uid(uid: str) -> bool:
return bool(re.match(r"^[a-zA-Z0-9_-]{3,100}$", uid))
def is_valid_email(email: str) -> bool:
return bool(re.match(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", email))