52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
# -*- 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)
|