Files
SkinsPins/app/avatar.py
T
Rolf 3a1da1482c Add full SkinsPins application
- FastAPI + SQLite + Alpine.js + HTMX PWA for Bingo Bango Bongo golf scoring
- Passwordless magic link auth with email (aiosmtplib) and admin invite system
- Real-time score entry via WebSocket with drag-and-drop player ordering
- Course management with per-hole par and stroke index
- Scorecard with golf score markers (birdie, eagle, bogey, etc.)
- Two-step new game form with tee selection per player
- Dashboard with stats, live games social stream, and recent game history
- Game summary view (read-only scorecard with leaderboard)
- User profile pages with win stats
- PWA install support with generated PNG icons
- Admin panel for users, courses, games, and invitations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 10:16:46 +01:00

30 lines
996 B
Python

import os
from pathlib import Path
from fastapi import UploadFile
AVATARS_DIR = Path(os.getenv("DATABASE_PATH", "/data/skinspins.db")).parent / "avatars"
ALLOWED_TYPES = {"image/jpeg", "image/png", "image/webp", "image/gif"}
MAX_SIZE = 2 * 1024 * 1024 # 2 MB
async def save_avatar(file: UploadFile, user_id: str) -> tuple[str | None, str | None]:
"""Returns (url_path, error). url_path is like /avatars/user_id.jpg"""
if file.content_type not in ALLOWED_TYPES:
return None, "Only JPEG, PNG, WebP or GIF images are allowed."
data = await file.read()
if len(data) > MAX_SIZE:
return None, "Image must be smaller than 2 MB."
ext = file.content_type.split("/")[-1].replace("jpeg", "jpg")
filename = f"{user_id}.{ext}"
dest = AVATARS_DIR / filename
# Remove any previous avatar for this user
for old in AVATARS_DIR.glob(f"{user_id}.*"):
old.unlink(missing_ok=True)
dest.write_bytes(data)
return f"/avatars/{filename}", None