Files
server-core/app/services/avatar_pool.py
T

52 lines
1.7 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""默认头像池:新用户未提供头像时,从头像池随机分配一个默认头像。
头像池 = 对象存储桶 avatar/images/images/ 目录下的 1321 张头像
(对象 key 清单见 ``serverdata/avatar_pool.json``,由 code/images/images_data/images
本地目录与桶内对象一一对应生成)。
数据库只存对象相对路径 ``/oss/avatar/images/images/<file>``
读取时经 ``resolve_url`` 补全为 CDN 直链(见 app/infrastructure/oss.py)。
语义约定:
- 新用户创建时若未显式提供头像(avatar 为空)→ 随机分配一个默认头像;
- 用户一旦自行更换头像(上传真实头像)→ 走 update 流程,不再回退/重随机。
"""
from __future__ import annotations
import json
import random
from pathlib import Path
from typing import List
from .. import config
_POOL_CACHE: List[str] | None = None
_POOL_PATH: Path = config.SERVERDATA_DIR / "avatar_pool.json"
def _load_pool() -> List[str]:
"""读取头像池对象 key 清单(内存缓存)。文件缺失/损坏时返回空池。"""
global _POOL_CACHE
if _POOL_CACHE is not None:
return _POOL_CACHE
try:
raw = json.loads(_POOL_PATH.read_text(encoding="utf-8"))
keys = [
str(k).strip()
for k in raw
if isinstance(k, str) and k.strip()
]
except Exception: # noqa: BLE001
keys = []
_POOL_CACHE = keys
return keys
def random_default_avatar() -> str:
"""从默认头像池随机返回一个对象路径(``/oss/...``);池为空时返回空串。"""
pool = _load_pool()
if not pool:
return ""
return "/oss/" + random.choice(pool)