forked from retoor/devplacepy
Working with avatars/
This commit is contained in:
@@ -59,6 +59,9 @@ async def signup(request: Request):
|
||||
)
|
||||
|
||||
uid = generate_uid()
|
||||
avatar_style = form.get("avatar_style", "initials")
|
||||
if avatar_style not in ("adventurer", "adventurer-neutral", "avataaars", "big-ears", "big-smile", "bottts", "croodles", "fun-emoji", "identicon", "initials", "lorelei", "micah", "miniavs", "notionists", "open-peeps", "personas", "pixel-art", "shapes", "thumbs"):
|
||||
avatar_style = "initials"
|
||||
users.insert({
|
||||
"uid": uid,
|
||||
"username": username,
|
||||
@@ -68,7 +71,7 @@ async def signup(request: Request):
|
||||
"location": "",
|
||||
"git_link": "",
|
||||
"website": "",
|
||||
"avatar": "",
|
||||
"avatar_style": avatar_style,
|
||||
"role": "Member",
|
||||
"level": 1,
|
||||
"xp": 0,
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import logging
|
||||
import httpx
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import Response
|
||||
from devplacepy.avatar import dicebear_proxy_url
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
_cache = {}
|
||||
|
||||
|
||||
def _initial_svg(seed: str) -> str:
|
||||
initial = seed[:1].upper() if seed else "?"
|
||||
return (
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">'
|
||||
f'<rect width="100" height="100" rx="50" fill="#ff6b35"/>'
|
||||
f'<text x="50" y="65" text-anchor="middle" fill="white" font-size="40" font-weight="700" font-family="sans-serif">{initial}</text></svg>'
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{style}/{seed}")
|
||||
async def avatar_proxy(request: Request, style: str, seed: str, size: int = 128):
|
||||
cache_key = f"{style}:{seed}:{size}"
|
||||
if cache_key in _cache:
|
||||
return Response(content=_cache[cache_key], media_type="image/svg+xml")
|
||||
|
||||
if style == "initials" or not style:
|
||||
svg = _initial_svg(seed)
|
||||
_cache[cache_key] = svg
|
||||
return Response(content=svg, media_type="image/svg+xml")
|
||||
|
||||
url = dicebear_proxy_url(style, seed, size)
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=3.0) as client:
|
||||
resp = await client.get(url, follow_redirects=True)
|
||||
content_type = resp.headers.get("content-type", "image/svg+xml")
|
||||
body = resp.content
|
||||
_cache[cache_key] = body
|
||||
return Response(content=body, media_type=content_type)
|
||||
except Exception as e:
|
||||
logger.warning(f"Avatar proxy failed for {style}/{seed}: {e}")
|
||||
svg = _initial_svg(seed)
|
||||
_cache[cache_key] = svg
|
||||
return Response(content=svg, media_type="image/svg+xml")
|
||||
@@ -61,10 +61,10 @@ async def view_post(request: Request, post_uid: str):
|
||||
|
||||
comments_table = get_table("comments")
|
||||
raw_comments = list(comments_table.find(post_uid=post_uid, order_by=["created_at"]))
|
||||
comments = []
|
||||
comment_map = {}
|
||||
for c in raw_comments:
|
||||
commenter = users_table.find_one(uid=c["user_uid"])
|
||||
comments.append({
|
||||
comment_map[c["uid"]] = {
|
||||
"comment": c,
|
||||
"author": commenter,
|
||||
"time_ago": time_ago(c["created_at"]),
|
||||
@@ -72,13 +72,22 @@ async def view_post(request: Request, post_uid: str):
|
||||
"up": len(list(get_table("votes").find(target_uid=c["uid"], value=1))),
|
||||
"down": len(list(get_table("votes").find(target_uid=c["uid"], value=-1))),
|
||||
},
|
||||
})
|
||||
"children": [],
|
||||
}
|
||||
|
||||
top_level = []
|
||||
for item in comment_map.values():
|
||||
parent_uid = item["comment"].get("parent_uid")
|
||||
if parent_uid and parent_uid in comment_map:
|
||||
comment_map[parent_uid]["children"].append(item)
|
||||
else:
|
||||
top_level.append(item)
|
||||
|
||||
return templates.TemplateResponse("post.html", {
|
||||
"request": request,
|
||||
"user": user,
|
||||
"post": post,
|
||||
"author": author,
|
||||
"comments": comments,
|
||||
"comments": top_level,
|
||||
"time_ago": time_ago(post["created_at"]),
|
||||
})
|
||||
|
||||
@@ -52,15 +52,21 @@ async def update_profile(request: Request):
|
||||
location = form.get("location", "").strip()
|
||||
git_link = form.get("git_link", "").strip()
|
||||
website = form.get("website", "").strip()
|
||||
avatar_style = form.get("avatar_style", "").strip()
|
||||
|
||||
users = get_table("users")
|
||||
users.update({
|
||||
update_data = {
|
||||
"uid": user["uid"],
|
||||
"bio": bio,
|
||||
"location": location,
|
||||
"git_link": git_link,
|
||||
"website": website,
|
||||
}, ["uid"])
|
||||
}
|
||||
valid_styles = ("adventurer", "adventurer-neutral", "avataaars", "big-ears", "big-smile", "bottts", "croodles", "fun-emoji", "identicon", "initials", "lorelei", "micah", "miniavs", "notionists", "open-peeps", "personas", "pixel-art", "shapes", "thumbs")
|
||||
if avatar_style in valid_styles:
|
||||
update_data["avatar_style"] = avatar_style
|
||||
|
||||
users.update(update_data, ["uid"])
|
||||
|
||||
logger.info(f"Profile updated for {user['username']}")
|
||||
return RedirectResponse(url=f"/profile/{user['username']}", status_code=302)
|
||||
|
||||
Reference in New Issue
Block a user