Files
rehearshalhub/api/src/rehearsalhub/services/avatar.py
Mistral Vibe cd6fabb31c fix: correct avatar upload and DiceBear URL version
- Add api.upload() to client.ts that passes FormData without setting
  Content-Type, letting the browser set multipart/form-data with the
  correct boundary (was causing 422 on the upload endpoint)
- Use api.upload() instead of api.post() for avatar file upload
- Update DiceBear URLs from v6 to 9.x in both frontend and backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:17:21 +02:00

55 lines
1.7 KiB
Python

"""Avatar generation service using DiceBear API."""
from typing import Optional
import httpx
from rehearsalhub.db.models import Member
class AvatarService:
"""Service for generating and managing user avatars."""
def __init__(self):
self.base_url = "https://api.dicebear.com/9.x"
async def generate_avatar_url(self, seed: str, style: str = "identicon") -> str:
"""Generate a DiceBear avatar URL for the given seed.
Args:
seed: Unique identifier (user ID, email, etc.)
style: Avatar style (default: identicon)
Returns:
URL to the generated avatar
"""
# Clean the seed for URL usage
clean_seed = seed.replace("-", "").replace("_", "")
# Construct DiceBear URL
return f"{self.base_url}/{style}/svg?seed={clean_seed}&backgroundType=gradientLinear&size=128"
async def generate_default_avatar(self, member: Member) -> str:
"""Generate a default avatar for a member using their ID as seed.
Args:
member: Member object
Returns:
URL to the generated avatar
"""
return await self.generate_avatar_url(str(member.id))
async def get_avatar_url(self, member: Member) -> Optional[str]:
"""Get the avatar URL for a member, generating default if none exists.
Args:
member: Member object
Returns:
Avatar URL or None
"""
if member.avatar_url:
return member.avatar_url
# Generate default avatar if none exists
return await self.generate_default_avatar(member)